mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89ab06a0d9 | |||
| 85266283c4 | |||
| b0a9f6505c | |||
| 8c40eb20ea | |||
| 25ff7ab350 | |||
| ad90251596 | |||
| ed05374054 | |||
| b5681f2412 | |||
| bd9923ab7e | |||
| 9dece6004e | |||
| 654782afe1 | |||
| 903f0239b2 | |||
| dda929c0a9 | |||
| 2482048449 | |||
| f54ee83938 | |||
| f5316eb320 | |||
| 500eebefde | |||
| d9cb95b2e9 | |||
| ce6554c3f1 | |||
| 7dcd690a05 | |||
| f376f22ad0 | |||
| ab586c4b00 | |||
| 64cbfaa974 | |||
| 3cab343919 | |||
| 1ad8c1f407 | |||
| 4e6db50049 | |||
| e62cef5644 | |||
| d6a56003aa | |||
| 8a5870300d | |||
| 42885b2a12 | |||
| 96216d5126 | |||
| d890ce1b94 | |||
| d1ff4f7014 | |||
| 9f3089566c | |||
| 79105bf400 | |||
| 2b0b74af92 | |||
| c65d164167 | |||
| 74bde0c7ea | |||
| 7fba61cb64 | |||
| b609e1d174 | |||
| bdbd484690 | |||
| cc5383b0f2 | |||
| 35d2653f56 | |||
| d6fa7710dc | |||
| fdb6d81bf0 | |||
| 6a03d446a3 | |||
| 4a0e6b0676 | |||
| fc4a11bc3e | |||
| e95abd6b37 | |||
| 0b4304474e | |||
| f36fb81249 | |||
| b17c157e18 | |||
| c86985017f | |||
| cb7562cd8c | |||
| ae6aaa0461 | |||
| c96a6c7e49 | |||
| 74b5e80cbc | |||
| 51c5c333e9 | |||
| f09ed5bbc5 | |||
| f0abdd87e3 | |||
| 7f091669c7 | |||
| 8dbee35757 | |||
| 1a2eaff1e6 | |||
| 36364bc09b | |||
| fcb4ced610 | |||
| 5df66e59d2 | |||
| 809cd5b268 | |||
| 661527a80f | |||
| 9883e75f05 | |||
| c3297d168f | |||
| 627e0ba391 | |||
| b29935ae47 | |||
| e1a907203e | |||
| 3cd1ddb3ad | |||
| b46e116712 | |||
| 44194d6055 | |||
| 47fd058f44 | |||
| c73fcafb15 | |||
| beb6d93f7b | |||
| d62aa14ca7 | |||
| a439ca5cde | |||
| 0736153fd6 | |||
| 0bce5f1a22 | |||
| feb43bb382 | |||
| 0bfd15aaad | |||
| 15f395a8e0 | |||
| a61040a0e2 | |||
| 8766b4d77b | |||
| 8c1214612a | |||
| 608d92f834 | |||
| ad6ab9eb36 | |||
| 0eda8d8a0f | |||
| b19691b5a4 | |||
| c7331aa556 | |||
| a440c050e5 | |||
| b9d45a9bb9 | |||
| 67482de7a9 | |||
| 04bedbef07 | |||
| a4abfb733a | |||
| 76d276436b | |||
| e7198f22d5 | |||
| 5bd20e173f | |||
| 15c4bb13e8 | |||
| b74eb5c035 | |||
| ed3a68af1e | |||
| 447b82c880 | |||
| 5700f8c1c6 | |||
| 1cf230d6b6 | |||
| 1ffd4b2f0b | |||
| 92ce780d6f | |||
| a2de3303e8 | |||
| 47a1981002 | |||
| b97bc5d1a9 | |||
| cc927fdc0e | |||
| 5dc2693106 | |||
| 472ce66ca7 | |||
| 796771554f | |||
| 28cb5d4c83 | |||
| a670aec986 | |||
| 51c54b9b53 | |||
| fa99385ff0 | |||
| 70a3b893a6 | |||
| c32a941906 | |||
| 8b597d10f9 | |||
| cedfcfd262 | |||
| 12add75232 | |||
| 4d29a24768 | |||
| 8626b86961 | |||
| 754dc1de1f | |||
| 3d1d4ca609 | |||
| 990b10b6f0 | |||
| 7462cd720e | |||
| 6bc83eb3b3 | |||
| dbec551c84 | |||
| 82cca5eca2 | |||
| 65f3cc1b3d | |||
| fae048dd69 | |||
| 854e3df49f | |||
| f6167c3b5e | |||
| ffe3e88b3b | |||
| caa3077f48 | |||
| 05dbf0b504 | |||
| 810e95198e | |||
| 10004f16b4 | |||
| 8e19748c7c | |||
| 17762a2e70 | |||
| 7dbd607a3f | |||
| 035e8a227e | |||
| 04eaf6606d | |||
| e558e93410 | |||
| e55fe3a8d5 | |||
| 8f075b99b5 | |||
| 09a0b3c373 | |||
| 4df4977733 | |||
| 6434feb980 | |||
| bc3e4b3e6f | |||
| c2a9e2254c | |||
| 251dd208af | |||
| afd1bbfc0f | |||
| a699f6c164 | |||
| 844cbfab53 | |||
| f74d5d29f9 |
@@ -1,9 +1,6 @@
|
|||||||
# EasyConfiguration Javadoc
|
# configured Javadoc
|
||||||
|
|
||||||
基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/EasyConfiguration) 。
|
Based
|
||||||
|
on [Github Pages](https://pages.github.com/),
|
||||||
## 如何实现?
|
please
|
||||||
|
see [JavaDoc](https://carmjos.github.io/configured) 。
|
||||||
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
|
|
||||||
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/) ,
|
|
||||||
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
|
|
||||||
|
|||||||
+2
-15
@@ -1,16 +1,3 @@
|
|||||||
# 欢迎使用 EasyConfiguration !
|
# Documentation
|
||||||
|
|
||||||
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
|
See [wiki](https://github.com/CarmJos/configured/wiki).
|
||||||
|
|
||||||
|
|
||||||
## 基本定义
|
|
||||||
|
|
||||||
Value: 实际配置的单例值。
|
|
||||||
|
|
||||||
Manifest: 用于描述值基本配置的对象。
|
|
||||||
|
|
||||||
Provider: 用于提供配置文件的接口。
|
|
||||||
|
|
||||||
Wrapper: 用于包装配置文件的接口。
|
|
||||||
|
|
||||||
Initializer: 用于初始化的接口
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 23 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
+346
@@ -0,0 +1,346 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
tab_width = 4
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
indent_size = 4
|
||||||
|
max_line_length = 120
|
||||||
|
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_new_line_in_record_component = false
|
||||||
|
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_field_with_annotations = 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_blank_lines_between_record_components = 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 =
|
||||||
|
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_prefix =
|
||||||
|
ij_java_entity_dd_suffix = EJB
|
||||||
|
ij_java_entity_eb_prefix =
|
||||||
|
ij_java_entity_eb_suffix = Bean
|
||||||
|
ij_java_entity_hi_prefix =
|
||||||
|
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_li_suffix =
|
||||||
|
ij_java_entity_pk_class = java.lang.String
|
||||||
|
ij_java_entity_ri_prefix =
|
||||||
|
ij_java_entity_ri_suffix =
|
||||||
|
ij_java_entity_vo_prefix =
|
||||||
|
ij_java_entity_vo_suffix = VO
|
||||||
|
ij_java_enum_constants_wrap = off
|
||||||
|
ij_java_enum_field_annotation_wrap = off
|
||||||
|
ij_java_extends_keyword_wrap = off
|
||||||
|
ij_java_extends_list_wrap = off
|
||||||
|
ij_java_field_annotation_wrap = split_into_lines
|
||||||
|
ij_java_field_name_prefix =
|
||||||
|
ij_java_field_name_suffix =
|
||||||
|
ij_java_filter_class_prefix =
|
||||||
|
ij_java_filter_class_suffix =
|
||||||
|
ij_java_filter_dd_prefix =
|
||||||
|
ij_java_filter_dd_suffix =
|
||||||
|
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_generate_use_type_annotation_before_type = true
|
||||||
|
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_on_demand_import_from_same_package_first = true
|
||||||
|
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_listener_class_prefix =
|
||||||
|
ij_java_listener_class_suffix =
|
||||||
|
ij_java_local_variable_name_prefix =
|
||||||
|
ij_java_local_variable_name_suffix =
|
||||||
|
ij_java_message_dd_prefix =
|
||||||
|
ij_java_message_dd_suffix = EJB
|
||||||
|
ij_java_message_eb_prefix =
|
||||||
|
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_new_line_when_body_is_presented = false
|
||||||
|
ij_java_packages_to_use_import_on_demand = java.awt.*, javax.swing.*
|
||||||
|
ij_java_parameter_annotation_wrap = off
|
||||||
|
ij_java_parameter_name_prefix =
|
||||||
|
ij_java_parameter_name_suffix =
|
||||||
|
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_preserve_module_imports = true
|
||||||
|
ij_java_record_components_wrap = normal
|
||||||
|
ij_java_repeat_annotations =
|
||||||
|
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_servlet_class_prefix =
|
||||||
|
ij_java_servlet_class_suffix =
|
||||||
|
ij_java_servlet_dd_prefix =
|
||||||
|
ij_java_servlet_dd_suffix =
|
||||||
|
ij_java_session_dd_prefix =
|
||||||
|
ij_java_session_dd_suffix = EJB
|
||||||
|
ij_java_session_eb_prefix =
|
||||||
|
ij_java_session_eb_suffix = Bean
|
||||||
|
ij_java_session_hi_prefix =
|
||||||
|
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_li_suffix =
|
||||||
|
ij_java_session_ri_prefix =
|
||||||
|
ij_java_session_ri_suffix =
|
||||||
|
ij_java_session_si_prefix =
|
||||||
|
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_inside_block_braces_when_body_is_present = 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_static_field_name_prefix =
|
||||||
|
ij_java_static_field_name_suffix =
|
||||||
|
ij_java_subclass_name_prefix =
|
||||||
|
ij_java_subclass_name_suffix = Impl
|
||||||
|
ij_java_switch_expressions_wrap = normal
|
||||||
|
ij_java_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_java_ternary_operation_wrap = off
|
||||||
|
ij_java_test_name_prefix =
|
||||||
|
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
|
||||||
|
ij_java_wrap_semicolon_after_call_chain = false
|
||||||
|
|
||||||
|
[*.xml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
max_line_length = 120
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
max_line_length = 120
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
max_line_length = 120
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = 500
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@@ -1,2 +1 @@
|
|||||||
github: [ CarmJos ]
|
github: [ CarmJos ]
|
||||||
custom: [ 'https://donate.carm.cc' ]
|
|
||||||
|
|||||||
@@ -1,37 +1,34 @@
|
|||||||
---
|
---
|
||||||
name: 问题提交
|
name: Submit bugs&issues
|
||||||
about: 描述问题并提交,帮助我们对其进行检查与修复。
|
about: Describe the problem and submit it to help us review and fix it.
|
||||||
title: ''
|
title: 'fix: '
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **问题简述**
|
### **Description**
|
||||||
|
|
||||||
用简短的话语描述一下大概问题。
|
<!-- Describe the general problem in short words.-->
|
||||||
|
|
||||||
### **问题来源**
|
### **Operations**
|
||||||
|
|
||||||
描述一下通过哪些操作才发现的问题,如:
|
<!--
|
||||||
|
Describe the problem discovered through what operations, such as:
|
||||||
|
|
||||||
1. 使用了 '...'
|
1. Clicked '...'
|
||||||
2. 输入了 '....'
|
2. Typed '....'
|
||||||
3. 出现了报错 '....'
|
3. Error says '....'
|
||||||
|
-->
|
||||||
|
|
||||||
### **预期结果** (可选)
|
### **Expected result** _(Optional)_
|
||||||
|
|
||||||
如果问题不发生,应该是什么情况
|
### **Screenshots & Error Logs**
|
||||||
|
|
||||||
### **问题截图/问题报错**
|
### **Environment**
|
||||||
|
|
||||||
如果有报错或输出,请提供截图。
|
- System: `Windows 10` / `Ubuntu` / `...`
|
||||||
|
- Java version: `JDK11` / `OPENJDK8` / `JRE8` / `...`
|
||||||
|
|
||||||
### **操作环境**
|
### **Anything else...**
|
||||||
|
|
||||||
- 系统环境: `Windows 10` / `Ubuntu` / `...`
|
<!-- If there are other supplements, they can be described here. -->
|
||||||
- Java版本: `JDK11` / `OPENJDK8` / `JRE8` / `...`
|
|
||||||
|
|
||||||
### **其他补充**
|
|
||||||
|
|
||||||
如有其他补充,可以在这里描述。
|
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
---
|
---
|
||||||
name: 功能需求
|
name: Features
|
||||||
about: 希望我们提供更多的功能。
|
about: Ask for new features.
|
||||||
title: ''
|
title: 'feat: '
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
---
|
---
|
||||||
|
|
||||||
### **功能简述**
|
### **Description**
|
||||||
|
|
||||||
简单的描述一下你想要的功能
|
<!-- Describe the features in short words.-->
|
||||||
|
|
||||||
### **需求来源**
|
### **Source**
|
||||||
|
|
||||||
简单的描述一下为什么需要这个功能。
|
<!-- Describe the reason that you need this feature in short words.-->
|
||||||
|
|
||||||
### **功能参考**(可选)
|
### **Examples** _(Optional)_
|
||||||
|
|
||||||
如果有相关功能的参考,如文本、截图,请提供给我们。
|
<!--Any screenshots or example codes please.-->
|
||||||
|
|
||||||
### **附加内容**
|
### **Additional details**
|
||||||
|
|
||||||
如果有什么小细节需要重点注意,请在这里告诉我们。
|
<!--If there are any small details that need to be highlighted, please let us know here.-->
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
# This workflow uses actions that are not certified by GitHub.
|
|
||||||
# They are provided by a third-party and are governed by
|
|
||||||
# separate terms of service, privacy policy, and support
|
|
||||||
# documentation.
|
|
||||||
|
|
||||||
# This workflow checks out code, performs a Codacy security scan
|
|
||||||
# and integrates the results with the
|
|
||||||
# GitHub Advanced Security code scanning feature. For more information on
|
|
||||||
# the Codacy security scan action usage and parameters, see
|
|
||||||
# https://github.com/codacy/codacy-analysis-cli-action.
|
|
||||||
# For more information on Codacy Analysis CLI in general, see
|
|
||||||
# https://github.com/codacy/codacy-analysis-cli.
|
|
||||||
|
|
||||||
name: "Codacy Security Scan"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ master ]
|
|
||||||
schedule:
|
|
||||||
- cron: '27 16 * * 5'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
codacy-security-scan:
|
|
||||||
name: Codacy Security Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# Checkout the repository to the GitHub Actions runner
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
|
||||||
- name: Run Codacy Analysis CLI
|
|
||||||
uses: codacy/codacy-analysis-cli-action@09916000460adeeedc96b9704f86deba53e2ad5d
|
|
||||||
with:
|
|
||||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
|
||||||
# You can also omit the token and run the tools that support default configurations
|
|
||||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
|
||||||
verbose: true
|
|
||||||
output: results.sarif
|
|
||||||
format: sarif
|
|
||||||
# Adjust severity of non-security issues
|
|
||||||
gh-code-scanning-compat: true
|
|
||||||
# Force 0 exit code to allow SARIF file generation
|
|
||||||
# This will handover control about PR rejection to the GitHub side
|
|
||||||
max-allowed-issues: 2147483647
|
|
||||||
|
|
||||||
# Upload the SARIF file generated in the previous step
|
|
||||||
- name: Upload SARIF results file
|
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
||||||
@@ -38,11 +38,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -53,7 +53,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v3
|
uses: github/codeql-action/autobuild@v4
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -67,4 +67,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v4
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Set up JDK"
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
java-version: '11'
|
java-version: '21'
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
cache: maven
|
cache: maven
|
||||||
server-id: github
|
server-id: github
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
id: sitemap
|
id: sitemap
|
||||||
uses: cicirello/generate-sitemap@v1
|
uses: cicirello/generate-sitemap@v1
|
||||||
with:
|
with:
|
||||||
base-url-path: https://CarmJos.github.io/EasyConfiguration
|
base-url-path: https://CarmJos.github.io/configured
|
||||||
path-to-root: docs
|
path-to-root: docs
|
||||||
|
|
||||||
- name: "Output stats"
|
- name: "Output stats"
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd docs
|
cd docs
|
||||||
git init
|
git init
|
||||||
git remote add origin git@github.com:CarmJos/EasyConfiguration.git
|
git remote add origin git@github.com:CarmJos/configured.git
|
||||||
git checkout -b gh-pages
|
git checkout -b gh-pages
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "API Document generated."
|
git commit -m "API Document generated."
|
||||||
@@ -87,11 +87,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Set up JDK"
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
java-version: '11'
|
java-version: '21'
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
cache: maven
|
cache: maven
|
||||||
server-id: central
|
server-id: central
|
||||||
|
|||||||
@@ -15,18 +15,18 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Set up JDK"
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
java-version: '11'
|
java-version: '21'
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
- name: "Package"
|
- name: "Package"
|
||||||
run: mvn -B package --file pom.xml -Dgpg.skip
|
run: mvn -B package --file pom.xml -Dgpg.skip
|
||||||
- name: "Target Stage"
|
- name: "Target Stage"
|
||||||
run: mkdir staging && cp */target/*.jar staging
|
run: mkdir staging && cp */target/*.jar staging
|
||||||
- name: "Upload artifact"
|
- name: "Upload artifact"
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Artifact
|
name: Artifact
|
||||||
path: staging
|
path: staging
|
||||||
|
|||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
.idea/
|
.idea/*
|
||||||
|
!.idea/icon.svg
|
||||||
**/target/
|
**/target/
|
||||||
**.iml
|
**.iml
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule ".wiki"]
|
||||||
|
path = .wiki
|
||||||
|
url = https://github.com/CarmJos/configured.wiki.git
|
||||||
Generated
+36
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 23 KiB |
Submodule
+1
Submodule .wiki added at c79c6f4a43
@@ -0,0 +1,75 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
(English primary version – a brief Chinese note may follow. 中文提示:本文件英文为主,若理解存在困难可联系维护者。)
|
||||||
|
|
||||||
|
This project adopts the principles of the Contributor Covenant v2.1 (https://www.contributor-covenant.org/version/2/1/code_of_conduct/) with project‑specific clarifications below. By participating you agree to uphold this Code.
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
We strive to provide a harassment‑free, inclusive, friendly, and productive environment for everyone, regardless of age, body, disability, ethnicity, sex characteristics, gender identity or expression, level of experience, education, socio‑economic status, nationality, personal appearance, race, caste, religion (or lack thereof), sexual identity or orientation, or technical choices.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
Examples of behavior that contributes to a positive environment:
|
||||||
|
- Showing empathy and respect to all participants
|
||||||
|
- Giving and gracefully accepting constructive feedback
|
||||||
|
- Focusing on what is best for the project and community
|
||||||
|
- Being honest about mistakes and seeking improvement
|
||||||
|
- Using welcoming and inclusive language
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
- Harassment, discrimination, or derogatory comments
|
||||||
|
- Trolling, insulting or antagonistic remarks, personal or political attacks
|
||||||
|
- Public or private harassment or sustained disruption of activities
|
||||||
|
- Publishing others’ private information without explicit permission
|
||||||
|
- Sexualized language, imagery, or unwelcome advances
|
||||||
|
- Any other conduct reasonably deemed inappropriate or unsafe
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
This Code applies within all project spaces (repository code, issues, pull requests, discussions, wiki, CI logs) and in public spaces whenever an individual is representing the project or community.
|
||||||
|
|
||||||
|
## Responsibilities & Enforcement
|
||||||
|
Project maintainers ("maintainers") are responsible for clarifying standards and taking appropriate, fair, and consistent corrective action.
|
||||||
|
|
||||||
|
Maintainers may remove or edit contributions that violate this Code (comments, commits, code, wiki edits, issues, discussions) and may temporarily or permanently ban any contributor for abusive, harassing, or otherwise harmful behavior.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
Report violations privately via:
|
||||||
|
- Email: carm@carm.cc
|
||||||
|
|
||||||
|
Please include (if possible):
|
||||||
|
- Links, timestamps, or message IDs
|
||||||
|
- Description of what happened and why it is a concern
|
||||||
|
- Screenshots or logs (if relevant)
|
||||||
|
- Preferred or suggested resolution
|
||||||
|
|
||||||
|
We aim to acknowledge reports within 72 hours and provide an initial assessment within 7 days. All good‑faith reports will be treated confidentially and only shared with individuals who need the information to resolve the issue.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
Maintainers will use these guidelines to determine the impact of an incident and consequences:
|
||||||
|
|
||||||
|
1. Correction
|
||||||
|
- Impact: Use of inappropriate language or other unprofessional conduct.
|
||||||
|
- Consequence: Private or public warning, request for change.
|
||||||
|
2. Warning
|
||||||
|
- Impact: A single severe incident or repeated inappropriate behavior.
|
||||||
|
- Consequence: Official warning; continued misconduct leads to escalation.
|
||||||
|
3. Temporary Suspension
|
||||||
|
- Impact: Persistent violations despite previous warnings.
|
||||||
|
- Consequence: Temporary participation suspension (issues/PRs/discussions). Conditions for reinstatement communicated.
|
||||||
|
4. Permanent Ban
|
||||||
|
- Impact: Demonstrated pattern of harassment, hate, or threats; refusal to reform.
|
||||||
|
- Consequence: Permanent removal from community spaces.
|
||||||
|
|
||||||
|
## Conflicts of Interest
|
||||||
|
Maintainers will recuse themselves from enforcement decisions where they have a personal conflict. A neutral maintainer or external trusted community member may be asked to assist when appropriate.
|
||||||
|
|
||||||
|
## Appeals
|
||||||
|
If you believe an enforcement action was made in error or was unfair, you may appeal by emailing the same reporting address within 14 days, providing context and justification.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
Portions adapted from Contributor Covenant v2.1 and other open source community best practices.
|
||||||
|
|
||||||
|
## Changes & Versioning
|
||||||
|
Substantive changes to this Code will be announced in the repository (Release Notes / CHANGELOG / Discussions). Historical versions will remain accessible via Git history.
|
||||||
|
|
||||||
|
---
|
||||||
|
If unsure whether something is acceptable: choose respect, transparency, and ask a maintainer before acting.
|
||||||
+210
@@ -0,0 +1,210 @@
|
|||||||
|
# Contributing Guide
|
||||||
|
|
||||||
|
> English is the primary language. A brief Chinese hint: 若需中文协助可在 Issue 中说明。
|
||||||
|
|
||||||
|
Thank you for investing time in contributing! This document describes how to propose changes and how we maintain quality and consistency across the project.
|
||||||
|
|
||||||
|
## Quick Links
|
||||||
|
- Code of Conduct: ./CODE_OF_CONDUCT.md
|
||||||
|
- Security Policy: ./SECURITY.md
|
||||||
|
- Issues: https://github.com/CarmJos/configured/issues
|
||||||
|
- Discussions / Q&A: (open an Issue if Discussions are disabled)
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
1. Principles
|
||||||
|
2. Scope of Contributions
|
||||||
|
3. Getting Started (Environment & Build)
|
||||||
|
4. Project Structure
|
||||||
|
5. Branching & Workflow
|
||||||
|
6. Issue Workflow
|
||||||
|
7. Pull Request Guidelines
|
||||||
|
8. Commit Message Convention
|
||||||
|
9. Coding Standards
|
||||||
|
10. Testing Guidelines
|
||||||
|
11. Documentation & JavaDoc
|
||||||
|
12. Dependency Policy
|
||||||
|
13. Versioning & Releases
|
||||||
|
14. Performance Expectations
|
||||||
|
15. Internationalization / Language
|
||||||
|
16. FAQ for Contributors
|
||||||
|
17. Attribution
|
||||||
|
|
||||||
|
---
|
||||||
|
## 1. Principles
|
||||||
|
We value: correctness, clarity, minimalism, maintainability, security-by-default, and performance without premature complexity. Every contribution should move at least one of these forward while not regressing the others.
|
||||||
|
|
||||||
|
## 2. Scope of Contributions
|
||||||
|
Acceptable contributions include (but are not limited to):
|
||||||
|
- Bug fixes & test coverage improvements
|
||||||
|
- Performance optimizations with measurable benefit
|
||||||
|
- New configuration providers (storage backends) with generic value
|
||||||
|
- Validation or serialization helpers
|
||||||
|
- Documentation, examples, or tutorials
|
||||||
|
- Tooling that improves developer productivity or release robustness
|
||||||
|
|
||||||
|
Out-of-scope (likely to be declined):
|
||||||
|
- Vendor lock‑in features narrowly targeting one proprietary platform (unless optional & isolated)
|
||||||
|
- Large feature branches without prior design discussion
|
||||||
|
- Unbounded abstraction that increases complexity with unclear user value
|
||||||
|
|
||||||
|
## 3. Getting Started (Environment & Build)
|
||||||
|
Requirements:
|
||||||
|
- JDK 8 (minimum). Later JDKs may work but target bytecode is 1.8.
|
||||||
|
- Maven 3.8+ (Wrapper optional; project assumes standard mvn).
|
||||||
|
|
||||||
|
Build all modules:
|
||||||
|
```bash
|
||||||
|
mvn -q clean verify
|
||||||
|
```
|
||||||
|
Skip tests (NOT recommended for PR validation):
|
||||||
|
```bash
|
||||||
|
mvn -q clean install -DskipTests
|
||||||
|
```
|
||||||
|
Run a single module:
|
||||||
|
```bash
|
||||||
|
mvn -q -pl core -am test
|
||||||
|
```
|
||||||
|
Generate JavaDoc (already bound in build):
|
||||||
|
```bash
|
||||||
|
mvn -q javadoc:javadoc
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Project Structure (High-level)
|
||||||
|
- core/ : Fundamental abstractions (Configuration, Value types, factories)
|
||||||
|
- features/ : Optional, orthogonal enhancements (validators, section, text, etc.)
|
||||||
|
- providers/ : Concrete persistence / parsing backends (yaml, gson, hocon, sql, mongodb, temp)
|
||||||
|
- demo/ : Usage demonstrations & sample scenarios
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- Core must not depend on feature or provider modules.
|
||||||
|
- Features must not form cycles; prefer depending only on core.
|
||||||
|
- Providers should keep external dependencies minimal and shaded/isolated only if necessary.
|
||||||
|
|
||||||
|
## 5. Branching & Workflow
|
||||||
|
- main (or master): Stable; only fast‑forward / squash from reviewed PRs.
|
||||||
|
- feature/<short-name>: New feature work. Open draft PR early for feedback.
|
||||||
|
- fix/<issue-id>-<slug>: Bug fix referencing an Issue.
|
||||||
|
- chore/<topic>: Build, infra, docs improvements.
|
||||||
|
|
||||||
|
Never force push to main. Force pushes allowed only to your own feature branches.
|
||||||
|
|
||||||
|
## 6. Issue Workflow
|
||||||
|
1. Search existing issues first to avoid duplication.
|
||||||
|
2. Provide reproduction steps (minimal code or config) for bugs.
|
||||||
|
3. Label suggestions as enhancement; performance items as perf.
|
||||||
|
4. For larger features, open a design issue summarizing: Problem, Motivation, Proposed API, Alternatives.
|
||||||
|
|
||||||
|
## 7. Pull Request Guidelines
|
||||||
|
Checklist before opening a PR:
|
||||||
|
- Linked to at least one Issue (unless trivial doc fix)
|
||||||
|
- Passes `mvn verify`
|
||||||
|
- Adds or updates tests covering new behavior / bug
|
||||||
|
- Includes JavaDoc / README / CHANGELOG fragment if user-facing
|
||||||
|
- No unrelated refactors or formatting churn
|
||||||
|
- Minimal diff: avoid reordering imports unless enforced by style
|
||||||
|
|
||||||
|
Review expectations:
|
||||||
|
- Maintainers strive to respond within 5 business days.
|
||||||
|
- Use constructive, action‑oriented comments.
|
||||||
|
- Resolve conversations or explain why not.
|
||||||
|
- Squash commits if they are noisy; retain meaningful logical grouping.
|
||||||
|
|
||||||
|
## 8. Commit Message Convention
|
||||||
|
Use Conventional Commits (https://www.conventionalcommits.org/) with optional scope:
|
||||||
|
```
|
||||||
|
<type>(<scope>): <short imperative summary>
|
||||||
|
|
||||||
|
<body>(optional)
|
||||||
|
|
||||||
|
<footer>(breaking changes, issue references)
|
||||||
|
```
|
||||||
|
Types used:
|
||||||
|
- feat: New feature (user visible)
|
||||||
|
- fix: Bug fix
|
||||||
|
- perf: Performance improvement
|
||||||
|
- refactor: Internal restructuring without behavior change
|
||||||
|
- docs: Documentation only
|
||||||
|
- test: Add or fix tests
|
||||||
|
- build: Build system or dependency changes
|
||||||
|
- ci: Continuous integration changes
|
||||||
|
- chore: Maintenance tasks
|
||||||
|
- style: Formatting (rare; avoid large style‑only changes)
|
||||||
|
|
||||||
|
Breaking changes: add `!` after type/scope or include `BREAKING CHANGE:` footer.
|
||||||
|
|
||||||
|
## 9. Coding Standards
|
||||||
|
- Java: Follow effective Java principles; prefer explicit types over inference for public APIs.
|
||||||
|
- Nullability: Use JetBrains annotations (`@NotNull`, `@Nullable`) where helpful.
|
||||||
|
- Immutability: Favor immutable value objects; avoid exposing mutable internal state.
|
||||||
|
- Exceptions: Use specific exception types; no swallowing silently. Validate inputs early.
|
||||||
|
- Logging: Keep core logging minimal; let consumers decide verbosity. Avoid println.
|
||||||
|
- APIs: Minimize surface; avoid exposing prematurely general interfaces.
|
||||||
|
- Annotations: Provide meaningful config path / comments metadata clearly.
|
||||||
|
|
||||||
|
### Style
|
||||||
|
- Indentation: 4 spaces.
|
||||||
|
- Line length guideline: ≤ 140 chars (soft limit).
|
||||||
|
- Avoid wildcard imports.
|
||||||
|
|
||||||
|
## 10. Testing Guidelines
|
||||||
|
- Use JUnit (current: JUnit 4). Prefer deterministic, isolated tests.
|
||||||
|
- Each bug fix must include a regression test failing before the fix.
|
||||||
|
- Avoid time‑sensitive sleeps; prefer deterministic constructs.
|
||||||
|
- Keep provider-specific integration tests under provider module.
|
||||||
|
- Use random data cautiously; if used, log seed for reproduction.
|
||||||
|
|
||||||
|
Command:
|
||||||
|
```bash
|
||||||
|
mvn -q test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. Documentation & JavaDoc
|
||||||
|
- Public classes & methods: brief JavaDoc describing contract, thread-safety, nullability.
|
||||||
|
- Add code examples when clarifying complex usage.
|
||||||
|
- Update README or module README for new feature flags or environment variables.
|
||||||
|
- Keep demo module aligned with latest recommended usage.
|
||||||
|
|
||||||
|
## 12. Dependency Policy
|
||||||
|
- Keep transitive dependency footprint lean.
|
||||||
|
- No large frameworks for simple utilities.
|
||||||
|
- Justify each new dependency in PR description (purpose, size, maintenance risk).
|
||||||
|
- Prefer stable, well-adopted libraries with permissive licenses compatible with LGPL.
|
||||||
|
- Security-sensitive libs (parsers, DB drivers) should be periodically updated.
|
||||||
|
|
||||||
|
## 13. Versioning & Releases
|
||||||
|
- Follows Semantic Versioning (MAJOR.MINOR.PATCH).
|
||||||
|
- Public API additions => MINOR bump.
|
||||||
|
- Backwards-compatible bug fix => PATCH.
|
||||||
|
- Backwards-incompatible change => MAJOR (document rationale & migration).
|
||||||
|
- Release steps (maintainers):
|
||||||
|
1. Ensure main is green (CI all passing)
|
||||||
|
2. Update CHANGELOG (if present) or Release Notes draft
|
||||||
|
3. Bump versions via maven-release-plugin (ensure GPG & staging configured)
|
||||||
|
4. Tag + push; verify publication (Central / GitHub Packages)
|
||||||
|
5. Publish GitHub Release with highlights + migration notes
|
||||||
|
|
||||||
|
## 14. Performance Expectations
|
||||||
|
- Avoid unnecessary object churn in hot paths.
|
||||||
|
- Profile before large rewrites. Provide benchmark or allocation stats if claiming improvement.
|
||||||
|
- Defer I/O and heavy parsing until needed (lazy loading pattern).
|
||||||
|
|
||||||
|
## 15. Internationalization / Language
|
||||||
|
- Primary language: English for code, comments, issues, PRs.
|
||||||
|
- Chinese clarifications acceptable if accompanied by English.
|
||||||
|
|
||||||
|
## 16. FAQ for Contributors
|
||||||
|
Q: Can I add a new provider?
|
||||||
|
A: Yes—open a design Issue first summarizing data model, external dependencies, and test strategy.
|
||||||
|
|
||||||
|
Q: How do I mark experimental APIs?
|
||||||
|
A: Add JavaDoc: `@apiNote Experimental: subject to change without notice.` and avoid wide promotion.
|
||||||
|
|
||||||
|
Q: Why Java 8 target?
|
||||||
|
A: Maximizes compatibility across server & embedded environments.
|
||||||
|
|
||||||
|
## 17. Attribution
|
||||||
|
Portions inspired by widely adopted open-source guidelines (Kotlin, Spring, Apache projects) and Conventional Commits.
|
||||||
|
|
||||||
|
---
|
||||||
|
Thank you for helping build a robust configuration ecosystem!
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|||||||
@@ -1,31 +1,30 @@
|
|||||||
```text
|
<div align=center>
|
||||||
____ _____ ____ __ _
|
<img src=".doc/images/banner.png" alt="Banner"/>
|
||||||
/ __/__ ____ __ __ / ___/__ ___ / _(_)__ ___ _________ _/ /_(_)__ ___
|
|
||||||
/ _// _ `(_-</ // / / /__/ _ \/ _ \/ _/ / _ `/ // / __/ _ `/ __/ / _ \/ _ \
|
[](https://github.com/CarmJos/configured/releases)
|
||||||
/___/\_,_/___/\_, / \___/\___/_//_/_//_/\_, /\_,_/_/ \_,_/\__/_/\___/_//_/
|
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||||
/___/ /___/
|
[](https://github.com/CarmJos/configured/actions/workflows/maven.yml)
|
||||||
```
|
[](https://www.codefactor.io/repository/github/carmjos/configured)
|
||||||
|

|
||||||
|
|
||||||
README LANGUAGES [ [**English**](README.md) | [中文](README_CN.md) ]
|
README LANGUAGES [ [**English**](README.md) | [中文](README_CN.md) ]
|
||||||
|
</div>
|
||||||
|
|
||||||
# EasyConfiguration
|
# configured _(config framework)_
|
||||||
|
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/releases)
|
<img src=".doc/images/logo-bg.svg" width="150px" alt="logo" align="right" style="float: right"/>
|
||||||
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
|
|
||||||
[](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
**Easy _(to make)_ Configurations!**
|
_**"Once set, Simple get."**_
|
||||||
|
|
||||||
A simple, easy-to-use and universal solution for managing configuration files.
|
A simple, easy-to-use and universal solution for managing, loading, reading,
|
||||||
Enjoy the ease of use with customizable formats for loading, reading, and updating your configuration files.
|
and updating configuration files.
|
||||||
|
|
||||||
|
Supported **JSON**, **YAML**, **Hocon**, **TOML**, **SQL**, **MongoDB**... and much more!
|
||||||
|
|
||||||
## Features & Advantages
|
## Features & Advantages
|
||||||
|
|
||||||
Supported [YAML](impl/yaml), [JSON](impl/json), [HOCON](impl/hocon) and [SQL](impl/sql) based configuration files
|
Supported [YAML](providers/yaml), [JSON](providers/json), [HOCON](providers/hocon) and [SQL](providers/sql)
|
||||||
format.
|
based configuration files format.
|
||||||
|
|
||||||
- Class-based mechanism for initializing, loading, retrieving, and updating configuration files, ensuring convenience
|
- Class-based mechanism for initializing, loading, retrieving, and updating configuration files, ensuring convenience
|
||||||
and efficiency.
|
and efficiency.
|
||||||
@@ -35,49 +34,51 @@ format.
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
For the latest JavaDoc release, [CLICK HERE](https://CarmJos.github.io/EasyConfiguration).
|
For the latest JavaDoc release, [CLICK HERE](https://CarmJos.github.io/configured).
|
||||||
|
|
||||||
For a detailed development guide, [CLICK HERE](.doc/README.md).
|
For a detailed development guide, see [wiki](https://github.com/CarmJos/configured/wiki).
|
||||||
|
|
||||||
### Code Samples
|
### Preview
|
||||||
|
|
||||||
To quickly demonstrate the applicability of the project, here are a few practical demonstrations:
|
To quickly demonstrate the applicability of the project, here are a few practical demonstrations:
|
||||||
|
|
||||||
- [Database configuration.](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java)
|
- [Database configuration.](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java)
|
||||||
- [Demonstration of all types of configuration instance classes.](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
|
- [Demonstration of configurations instance classes.](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
|
||||||
|
|
||||||
Check out all code demonstrations [HERE](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java).
|
Check out all code demonstrations [HERE](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java).
|
||||||
For more examples, see the [Development Guide](.doc/README.md).
|
For more examples, see the [Development Guide](.doc/README.md).
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@ConfigPath(root = true)
|
@ConfigPath(root = true)
|
||||||
@HeaderComments("Configurations for sample")
|
@HeaderComments("Configurations for sample")
|
||||||
public interface SampleConfig extends Configuration {
|
public interface SampleConfig extends Configuration {
|
||||||
|
|
||||||
@InlineComment("Enabled?") // Inline comment
|
@InlineComment("Enabled?") // Inline comment
|
||||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||||
|
|
||||||
@HeaderComments("Server configurations") // Header comment
|
@HeaderComments("Server configurations") // Header comment
|
||||||
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
|
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
|
||||||
|
|
||||||
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
|
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
|
||||||
@FooterComments("[ UUID >-----------------------------------")
|
@FooterComments("[ UUID >-----------------------------------")
|
||||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||||
.parse(UUID::fromString).serialize(UUID::toString)
|
.parse(UUID::fromString).serialize(UUID::toString)
|
||||||
.defaults(
|
.defaults(
|
||||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||||
).build();
|
).build();
|
||||||
|
|
||||||
@ConfigPath("info") // Custom path
|
@ConfigPath("info") // Custom path
|
||||||
interface INFO extends Configuration {
|
interface INFO extends Configuration {
|
||||||
|
|
||||||
@HeaderComments("Configure your name!") // Header comment
|
@HeaderComments("Configure your name!") // Header comment
|
||||||
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
||||||
|
|
||||||
@ConfigPath("how-old-are-you") // Custom path
|
@ConfigPath("how-old-are-you") // Custom path
|
||||||
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,23 +86,23 @@ public interface SampleConfig extends Configuration {
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
public class Sample {
|
public class Sample {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 1. Make a configuration provider from a file.
|
// 1. Make a configuration provider from a file.
|
||||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
||||||
.resourcePath("configs/sample.yml")
|
.resourcePath("configs/sample.yml")
|
||||||
.indent(4) // Optional: Set the indentation of the configuration file.
|
.indent(4) // Optional: Set the indentation of the configuration file.
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// 2. Initialize the configuration classes or instances.
|
// 2. Initialize the configuration classes or instances.
|
||||||
holder.initialize(SampleConfig.class);
|
holder.initialize(SampleConfig.class);
|
||||||
// 3. Enjoy using the configuration!
|
// 3. Enjoy using the configuration!
|
||||||
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve());
|
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve()); // true
|
||||||
SampleConfig.ENABLED.set(false);
|
SampleConfig.ENABLED.set(false);
|
||||||
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve());
|
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve()); // false
|
||||||
// p.s. Changes not save so enable value will still be true in the next run.
|
// p.s. Changes not save so enable value will still be true in the next run.
|
||||||
|
|
||||||
System.out.println("Your name is " + SampleConfig.INFO.NAME.resolve() + " (age=" + SampleConfig.INFO.AGE.resolve() + ")!");
|
System.out.println("Your name is " + SampleConfig.INFO.NAME.resolve() + " (age=" + SampleConfig.INFO.AGE.resolve() + ")!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -148,9 +149,9 @@ info:
|
|||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
<!-- Using GitHub dependencies for real-time updates, configuration required (recommended). -->
|
<!-- Using GitHub dependencies for real-time updates, configuration required (recommended). -->
|
||||||
<id>EasyConfiguration</id>
|
<id>configured</id>
|
||||||
<name>GitHub Packages</name>
|
<name>GitHub Packages</name>
|
||||||
<url>https://maven.pkg.github.com/CarmJos/EasyConfiguration</url>
|
<url>https://maven.pkg.github.com/CarmJos/configured</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
</repositories>
|
</repositories>
|
||||||
@@ -169,7 +170,7 @@ info:
|
|||||||
<!-- Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”. -->
|
<!-- Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”. -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -177,7 +178,7 @@ info:
|
|||||||
<!-- YAML file-based implementation, compatible with all Java environments. -->
|
<!-- YAML file-based implementation, compatible with all Java environments. -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-yaml</artifactId>
|
<artifactId>configured-yaml</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -185,7 +186,7 @@ info:
|
|||||||
<!-- JSON file-based implementation, compatible with all Java environments. -->
|
<!-- JSON file-based implementation, compatible with all Java environments. -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-gson</artifactId>
|
<artifactId>configured-gson</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -208,7 +209,7 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
// Using GitHub dependencies for real-time updates, configuration required (recommended).
|
// Using GitHub dependencies for real-time updates, configuration required (recommended).
|
||||||
maven { url 'https://maven.pkg.github.com/CarmJos/EasyConfiguration' }
|
maven { url 'https://maven.pkg.github.com/CarmJos/configured' }
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -223,13 +224,13 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
// Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”.
|
// Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”.
|
||||||
api "cc.carm.lib:easyconfiguration-core:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-core:[LATEST RELEASE]"
|
||||||
|
|
||||||
// YAML file-based implementation, compatible with all Java environments.
|
// YAML file-based implementation, compatible with all Java environments.
|
||||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-yaml:[LATEST RELEASE]"
|
||||||
|
|
||||||
// JSON file-based implementation, compatible with all Java environments.
|
// JSON file-based implementation, compatible with all Java environments.
|
||||||
api "cc.carm.lib:easyconfiguration-gson:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-gson:[LATEST RELEASE]"
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -240,7 +241,7 @@ dependencies {
|
|||||||
|
|
||||||
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos)
|
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos)
|
||||||
|
|
||||||
EasyConfiguration for MineCraft!
|
configured for MineCraft!
|
||||||
Easily manage configurations on MineCraft-related server platforms.
|
Easily manage configurations on MineCraft-related server platforms.
|
||||||
|
|
||||||
Currently, it supports BungeeCord, Velocity, Bukkit (Spigot) servers,
|
Currently, it supports BungeeCord, Velocity, Bukkit (Spigot) servers,
|
||||||
@@ -248,13 +249,13 @@ with more platforms to be supported soon.
|
|||||||
|
|
||||||
## Support and Donation
|
## Support and Donation
|
||||||
|
|
||||||
If you appreciate this plugin, consider supporting me with a donation!
|
If you appreciate this plugin, consider supporting me with a [donation](https://github.com/sponsors/CarmJos)!
|
||||||
|
|
||||||
Thank you for supporting open-source projects!
|
Thank you for supporting open-source projects!
|
||||||
|
|
||||||
Many thanks to Jetbrains for kindly providing a license for us to work on this and other open-source projects.
|
Many thanks to Jetbrains for kindly providing a license for us to work on this and other open-source projects.
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=https://github.com/CarmJos/EasyConfiguration)
|
[](https://www.jetbrains.com/?from=https://github.com/CarmJos/configured)
|
||||||
|
|
||||||
Many thanks to [ArtformGames](https://github.com/ArtformGames) for their
|
Many thanks to [ArtformGames](https://github.com/ArtformGames) for their
|
||||||
strong support and active contribution to this project!
|
strong support and active contribution to this project!
|
||||||
@@ -265,3 +266,4 @@ strong support and active contribution to this project!
|
|||||||
|
|
||||||
This project's source code is licensed under
|
This project's source code is licensed under
|
||||||
the [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html).
|
the [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html).
|
||||||
|
|
||||||
|
|||||||
+32
-34
@@ -1,29 +1,27 @@
|
|||||||
```text
|
<div align=center>
|
||||||
____ _____ ____ __ _
|
<img src=".doc/images/banner.png" alt="Banner"/>
|
||||||
/ __/__ ____ __ __ / ___/__ ___ / _(_)__ ___ _________ _/ /_(_)__ ___
|
|
||||||
/ _// _ `(_-</ // / / /__/ _ \/ _ \/ _/ / _ `/ // / __/ _ `/ __/ / _ \/ _ \
|
[](https://github.com/CarmJos/configured/releases)
|
||||||
/___/\_,_/___/\_, / \___/\___/_//_/_//_/\_, /\_,_/_/ \_,_/\__/_/\___/_//_/
|
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||||
/___/ /___/
|
[](https://github.com/CarmJos/configured/actions/workflows/maven.yml)
|
||||||
```
|
[](https://www.codefactor.io/repository/github/carmjos/configured)
|
||||||
|

|
||||||
|
|
||||||
README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
||||||
|
|
||||||
# EasyConfiguration
|
</div>
|
||||||
|
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/releases)
|
# configured _(配置文件框架)_
|
||||||
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
|
|
||||||
[](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
**轻松(做)配置!**
|
<img src=".doc/images/logo-bg.svg" width="150px" alt="logo" align="right" style="float: right"/>
|
||||||
|
|
||||||
|
**一次配置,轻松读取!**
|
||||||
|
|
||||||
一款简单便捷的通用配置文件加载、读取与更新工具,可自定义配置的格式。
|
一款简单便捷的通用配置文件加载、读取与更新工具,可自定义配置的格式。
|
||||||
|
|
||||||
## 特性 & 优势
|
## 特性 & 优势
|
||||||
|
|
||||||
支持 [YAML](impl/yaml), [JSON](impl/json), [HOCON](impl/hocon) 和 [SQL](impl/sql) 等多种配置文件格式。
|
支持 [YAML](providers/yaml), [JSON](providers/gson), [HOCON](providers/hocon) 和 [SQL](providers/sql) 等多种配置文件格式。
|
||||||
|
|
||||||
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
||||||
- 支持复杂配置的手动序列化、反序列化。
|
- 支持复杂配置的手动序列化、反序列化。
|
||||||
@@ -33,7 +31,7 @@ README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
|||||||
## 开发
|
## 开发
|
||||||
|
|
||||||
详细开发介绍请 [点击这里](.doc/README.md) , JavaDoc(最新Release)
|
详细开发介绍请 [点击这里](.doc/README.md) , JavaDoc(最新Release)
|
||||||
请 [点击这里](https://CarmJos.github.io/EasyConfiguration) 。
|
请 [点击这里](https://CarmJos.github.io/configured) 。
|
||||||
|
|
||||||
### 示例代码
|
### 示例代码
|
||||||
|
|
||||||
@@ -43,7 +41,7 @@ README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
|||||||
- [全种类配置实例类演示](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
|
- [全种类配置实例类演示](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
|
||||||
|
|
||||||
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo)
|
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo)
|
||||||
直接查看现有的代码演示,更多复杂情况演示详见 [开发介绍](.doc/README.md) 。
|
直接查看现有的代码演示,更多复杂情况演示详见 [开发介绍](https://github.com/CarmJos/configured/wiki) 。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -142,9 +140,9 @@ info:
|
|||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
|
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
|
||||||
<id>EasyConfiguration</id>
|
<id>configured</id>
|
||||||
<name>GitHub Packages</name>
|
<name>GitHub Packages</name>
|
||||||
<url>https://maven.pkg.github.com/CarmJos/EasyConfiguration</url>
|
<url>https://maven.pkg.github.com/CarmJos/configured</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
@@ -170,7 +168,7 @@ info:
|
|||||||
<!--基础实现部分,需要自行实现“Provider”与“Wrapper”。-->
|
<!--基础实现部分,需要自行实现“Provider”与“Wrapper”。-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -178,7 +176,7 @@ info:
|
|||||||
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
|
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-yaml</artifactId>
|
<artifactId>configured-yaml</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -187,21 +185,21 @@ info:
|
|||||||
<!--需要注意的是,JSON不支持文件注释。-->
|
<!--需要注意的是,JSON不支持文件注释。-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-gson</artifactId>
|
<artifactId>configured-gson</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-hocon</artifactId>
|
<artifactId>configured-hocon</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-sql</artifactId>
|
<artifactId>configured-sql</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -224,7 +222,7 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
// 采用github依赖库,实时更新,但需要配置 (推荐)
|
// 采用github依赖库,实时更新,但需要配置 (推荐)
|
||||||
maven { url 'https://maven.pkg.github.com/CarmJos/EasyConfiguration' }
|
maven { url 'https://maven.pkg.github.com/CarmJos/configured' }
|
||||||
|
|
||||||
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
|
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
|
||||||
maven { url 'https://repo.carm.cc/repository/maven-public/' }
|
maven { url 'https://repo.carm.cc/repository/maven-public/' }
|
||||||
@@ -241,18 +239,18 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
//基础实现部分,需要自行实现“Provider”与“Wrapper”。
|
//基础实现部分,需要自行实现“Provider”与“Wrapper”。
|
||||||
api "cc.carm.lib:easyconfiguration-core:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-core:[LATEST RELEASE]"
|
||||||
|
|
||||||
//基于YAML文件的实现版本,可用于全部Java环境。
|
//基于YAML文件的实现版本,可用于全部Java环境。
|
||||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-yaml:[LATEST RELEASE]"
|
||||||
|
|
||||||
//基于JSON文件的实现版本,可用于全部Java环境。
|
//基于JSON文件的实现版本,可用于全部Java环境。
|
||||||
//需要注意的是,JSON不支持文件注释。
|
//需要注意的是,JSON不支持文件注释。
|
||||||
api "cc.carm.lib:easyconfiguration-gson:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-gson:[LATEST RELEASE]"
|
||||||
|
|
||||||
api "cc.carm.lib:easyconfiguration-hocon:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-hocon:[LATEST RELEASE]"
|
||||||
|
|
||||||
api "cc.carm.lib:easyconfiguration-sql:[LATEST RELEASE]"
|
api "cc.carm.lib:configured-sql:[LATEST RELEASE]"
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -263,20 +261,20 @@ dependencies {
|
|||||||
|
|
||||||
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
|
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
|
||||||
|
|
||||||
EasyConfiguration for MineCraft!
|
configured for MineCraft!
|
||||||
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
|
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
|
||||||
|
|
||||||
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
|
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
|
||||||
|
|
||||||
## 支持与捐赠
|
## 支持与捐赠
|
||||||
|
|
||||||
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
若您觉得本插件做的不错,您可以通过[捐赠](https://github.com/sponsors/CarmJos)支持我!
|
||||||
|
|
||||||
感谢您对开源项目的支持!
|
感谢您对开源项目的支持!
|
||||||
|
|
||||||
万分感谢 Jetbrains 为我们提供了从事此项目和其他开源项目的许可!
|
万分感谢 Jetbrains 为我们提供了从事此项目和其他开源项目的许可!
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=https://github.com/CarmJos/EasyConfiguration)
|
[](https://www.jetbrains.com/?from=https://github.com/CarmJos/configured)
|
||||||
|
|
||||||
万分感谢来自 [ArtformGames](https://github.com/ArtformGames) 对本项目的大力支持与积极贡献!
|
万分感谢来自 [ArtformGames](https://github.com/ArtformGames) 对本项目的大力支持与积极贡献!
|
||||||
|
|
||||||
|
|||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
English is the authoritative language of this document.
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
We generally provide security fixes only for the latest released MINOR version (most recent tag on the default branch). Older versions may receive fixes only if the vulnerability is critical and a patch is low risk.
|
||||||
|
|
||||||
|
| Version | Status |
|
||||||
|
|----------|-------------------------|
|
||||||
|
| Latest | Security fixes |
|
||||||
|
| < Latest | Not routinely supported |
|
||||||
|
|
||||||
|
If you rely on an older version you are strongly encouraged to upgrade promptly after each release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please DO NOT open a public Issue for suspected security problems.
|
||||||
|
|
||||||
|
Instead, email: carm@carm.cc with:
|
||||||
|
|
||||||
|
- A clear description of the issue and potential impact
|
||||||
|
- Steps to reproduce (minimal code / configuration)
|
||||||
|
- Affected version(s) and environment (JDK, OS)
|
||||||
|
- Any known workarounds
|
||||||
|
- Preferred public credit name (optional)
|
||||||
|
|
||||||
|
You will receive an acknowledgement within 72 hours (workdays) confirming receipt.
|
||||||
|
|
||||||
|
## Assessment & Disclosure Process
|
||||||
|
|
||||||
|
1. Triage & validation (attempt reproduction, scope impact)
|
||||||
|
2. Determine severity (CVSS or qualitative: Low / Moderate / High / Critical)
|
||||||
|
3. Prepare a private fix / patch + regression tests
|
||||||
|
4. Coordinate an embargoed release window (typically ≤14 days after validation for High/Critical)
|
||||||
|
5. Release a new version (and possibly backport if warranted)
|
||||||
|
6. Publish security advisory (GitHub Security Advisory + Release Notes) including mitigation steps
|
||||||
|
|
||||||
|
We may reject reports that are clearly non‑security bugs (e.g., feature requests, performance tuning) or issues requiring unreasonable preconditions (e.g., attacker already has full local code execution).
|
||||||
|
|
||||||
|
## Non-Qualifying Issues (Examples)
|
||||||
|
|
||||||
|
- Missing rate limits on non-authenticated, non-state-changing operations
|
||||||
|
- Denial-of-service requiring unrealistic resource constraints or already solved via JVM flags
|
||||||
|
- Vulnerabilities only exploitable on unsupported / EOL Java versions
|
||||||
|
- Social engineering, SPF/DMARC issues beyond this codebase’s control
|
||||||
|
|
||||||
|
## Coordinated Disclosure
|
||||||
|
|
||||||
|
If you plan to blog or speak publicly about the vulnerability prior to patch availability, please coordinate timing so users can upgrade safely.
|
||||||
|
|
||||||
|
## Dependency Security
|
||||||
|
|
||||||
|
We periodically review dependency versions for CVEs. You can help by:
|
||||||
|
|
||||||
|
- Submitting PRs that upgrade vulnerable libraries with changelog & compatibility notes
|
||||||
|
- Avoiding unnecessary new dependencies
|
||||||
|
|
||||||
|
## Cryptographic Material
|
||||||
|
|
||||||
|
This project does not bundle custom cryptographic primitives. If you discover misuse of crypto APIs or insecure random number use in security-sensitive areas, treat it as a security report.
|
||||||
|
|
||||||
|
## Reporting Format Template (Recommended)
|
||||||
|
|
||||||
|
```
|
||||||
|
Subject: [Security Report] <short title>
|
||||||
|
|
||||||
|
Affected Component: (module / class)
|
||||||
|
Version(s) Tested: x.y.z (and earlier if known)
|
||||||
|
Environment: JDK x, OS
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
Describe the vulnerability and impact.
|
||||||
|
|
||||||
|
Reproduction Steps:
|
||||||
|
1. ...
|
||||||
|
2. ...
|
||||||
|
3. ...
|
||||||
|
|
||||||
|
Expected vs Actual:
|
||||||
|
|
||||||
|
Potential Impact:
|
||||||
|
|
||||||
|
Workarounds / Mitigations (if any):
|
||||||
|
|
||||||
|
Credit: (name / handle / anonymous)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Credit & Acknowledgement
|
||||||
|
|
||||||
|
We will list (with permission) reporters who submit valid, first responsibly disclosed security issues in the release notes / advisory.
|
||||||
|
|
||||||
|
## GPG / Integrity
|
||||||
|
|
||||||
|
Release artifacts are signed (see project docs). Always verify signatures and checksums when consuming artifacts from Maven Central or GitHub Packages.
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
For general (non-sensitive) questions, open an Issue labeled `question` rather than using the security email.
|
||||||
|
|
||||||
|
Thank you for helping keep the ecosystem safe.
|
||||||
|
|
||||||
+10
-3
@@ -3,9 +3,9 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>configured-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>4.0.7</version>
|
<version>4.2.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -15,9 +15,16 @@
|
|||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Configured - Core</name>
|
||||||
|
<url>https://github.com/CarmJos/configured</url>
|
||||||
|
<description>
|
||||||
|
The core module of Configured framework,
|
||||||
|
providing essential configuration management functionality.
|
||||||
|
</description>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ package cc.carm.lib.configuration;
|
|||||||
* The root interface of the configuration file interfaces,
|
* The root interface of the configuration file interfaces,
|
||||||
* which is used to label a class as a configuration.
|
* which is used to label a class as a configuration.
|
||||||
*/
|
*/
|
||||||
public interface Configuration { }
|
public interface Configuration {
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import java.util.Objects;
|
|||||||
* @param <TYPE> The type of the target value
|
* @param <TYPE> The type of the target value
|
||||||
*/
|
*/
|
||||||
public class ValueAdapter<TYPE>
|
public class ValueAdapter<TYPE>
|
||||||
implements ValueSerializer<TYPE>, ValueParser<TYPE> {
|
implements ValueSerializer<TYPE>, ValueParser<TYPE> {
|
||||||
|
|
||||||
protected final @NotNull ValueType<TYPE> type;
|
protected final @NotNull ValueType<TYPE> type;
|
||||||
|
|
||||||
protected @Nullable ValueSerializer<TYPE> serializer;
|
protected @Nullable ValueSerializer<TYPE> serializer;
|
||||||
protected @Nullable ValueParser<TYPE> deserializer;
|
protected @Nullable ValueParser<TYPE> deserializer;
|
||||||
|
|
||||||
@@ -53,13 +54,21 @@ public class ValueAdapter<TYPE>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object serialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull TYPE value) throws Exception {
|
public @Nullable Object serialize(
|
||||||
|
@NotNull ConfigurationHolder<?> holder,
|
||||||
|
@NotNull ValueType<? super TYPE> type,
|
||||||
|
@NotNull TYPE value
|
||||||
|
) throws Exception {
|
||||||
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
|
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
|
||||||
return serializer.serialize(holder, type, value);
|
return serializer.serialize(holder, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TYPE parse(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
|
public @Nullable TYPE parse(
|
||||||
|
@NotNull ConfigurationHolder<?> holder,
|
||||||
|
@NotNull ValueType<? super TYPE> type,
|
||||||
|
@NotNull Object value
|
||||||
|
) throws Exception {
|
||||||
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
|
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
|
||||||
return deserializer.parse(holder, type, value);
|
return deserializer.parse(holder, type, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ package cc.carm.lib.configuration.adapter;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import org.jetbrains.annotations.Contract;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.lang.reflect.Array;
|
||||||
import java.util.HashSet;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.Set;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class ValueAdapterRegistry {
|
public class ValueAdapterRegistry {
|
||||||
|
|
||||||
protected final Set<ValueAdapter<?>> adapters = new HashSet<>();
|
protected final Set<ValueAdapter<?>> adapters = new HashSet<>();
|
||||||
|
protected final Map<ValueType<?>, ValueAdapter<?>> adapterCache = new HashMap<>();
|
||||||
|
|
||||||
public <FROM, TO> void register(@NotNull Class<FROM> from, @NotNull Class<TO> to,
|
public <FROM, TO> void register(@NotNull Class<FROM> from, @NotNull Class<TO> to,
|
||||||
@Nullable DataFunction<FROM, TO> parser,
|
@Nullable DataFunction<FROM, TO> parser,
|
||||||
@@ -26,13 +28,14 @@ public class ValueAdapterRegistry {
|
|||||||
ValueAdapter<FROM> fromAdapter = adapterOf(from);
|
ValueAdapter<FROM> fromAdapter = adapterOf(from);
|
||||||
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
|
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
|
||||||
register(to,
|
register(to,
|
||||||
serializer == null ? null : (provider, type, value) -> fromAdapter.serialize(provider, from, serializer.handle(value)),
|
serializer == null ? null : (provider, type, value) -> fromAdapter.serialize(provider, from, serializer.handle(value)),
|
||||||
parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.parse(provider, from, data))
|
parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.parse(provider, from, data))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(@NotNull ValueAdapter<?>... adapter) {
|
public void register(@NotNull ValueAdapter<?>... adapter) {
|
||||||
adapters.addAll(Arrays.asList(adapter));
|
adapters.addAll(Arrays.asList(adapter));
|
||||||
|
adapterCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void register(@NotNull Class<T> type, @NotNull ValueSerializer<T> serializer) {
|
public <T> void register(@NotNull Class<T> type, @NotNull ValueSerializer<T> serializer) {
|
||||||
@@ -61,7 +64,9 @@ public class ValueAdapterRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void register(@NotNull ValueType<T> type, @Nullable ValueSerializer<T> serializer, @Nullable ValueParser<T> deserializer) {
|
public <T> void register(@NotNull ValueType<T> type,
|
||||||
|
@Nullable ValueSerializer<T> serializer,
|
||||||
|
@Nullable ValueParser<T> deserializer) {
|
||||||
if (serializer == null && deserializer == null) return;
|
if (serializer == null && deserializer == null) return;
|
||||||
ValueAdapter<T> existing = adapterOf(type);
|
ValueAdapter<T> existing = adapterOf(type);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
@@ -78,17 +83,31 @@ public class ValueAdapterRegistry {
|
|||||||
|
|
||||||
public void unregister(@NotNull ValueType<?> type) {
|
public void unregister(@NotNull ValueType<?> type) {
|
||||||
adapters.removeIf(adapter -> adapter.type().equals(type));
|
adapters.removeIf(adapter -> adapter.type().equals(type));
|
||||||
|
adapterCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> @Nullable ValueAdapter<T> adapterOf(@NotNull ValueType<T> type) {
|
public <T> @Nullable ValueAdapter<T> adapterOf(@NotNull ValueType<T> type) {
|
||||||
ValueAdapter<?> matched = adapters.stream().filter(adapter -> adapter.type().equals(type)).findFirst().orElse(null);
|
if (adapterCache.containsKey(type)) {
|
||||||
if (matched != null) return (ValueAdapter<T>) matched;
|
return (ValueAdapter<T>) adapterCache.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
// If no adapter found, try to find the adapter for the super type
|
for (ValueAdapter<?> adapter : adapters) {
|
||||||
return (ValueAdapter<T>) adapters.stream()
|
if (adapter.type().equals(type)) {
|
||||||
.filter(adapter -> adapter.type().isSubtypeOf(type))
|
adapterCache.put(type, adapter);
|
||||||
.findFirst().orElse(null);
|
return (ValueAdapter<T>) adapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ValueAdapter<?> adapter : adapters) {
|
||||||
|
if (adapter.type().isSubtypeOf(type)) {
|
||||||
|
adapterCache.put(type, adapter);
|
||||||
|
return (ValueAdapter<T>) adapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapterCache.put(type, null);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> ValueAdapter<T> adapterOf(@NotNull T value) {
|
public <T> ValueAdapter<T> adapterOf(@NotNull T value) {
|
||||||
@@ -99,28 +118,191 @@ public class ValueAdapterRegistry {
|
|||||||
return adapterOf(ValueType.of(type));
|
return adapterOf(ValueType.of(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,_,null -> null")
|
|
||||||
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull Class<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull Class<T> type, @Nullable Object source) throws Exception {
|
||||||
return deserialize(holder, ValueType.of(type), source);
|
return deserialize(holder, ValueType.of(type), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,_,null -> null")
|
|
||||||
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
||||||
if (source == null) return null; // Null check
|
if (source == null) return null;
|
||||||
if (type.isInstance(source)) return type.cast(source); // Not required to deserialize
|
|
||||||
|
Type typeInstance = type.getType();
|
||||||
|
if (!(typeInstance instanceof ParameterizedType) && type.isInstance(source)) {
|
||||||
|
return type.cast(source);
|
||||||
|
}
|
||||||
|
|
||||||
ValueAdapter<T> adapter = adapterOf(type);
|
ValueAdapter<T> adapter = adapterOf(type);
|
||||||
if (adapter == null) throw new RuntimeException("No adapter for type " + type);
|
if (adapter != null) {
|
||||||
return adapter.parse(holder, type, source);
|
return adapter.parse(holder, type, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserializeWithoutAdapter(holder, type, source, typeInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,null -> null")
|
private <T> T deserializeWithoutAdapter(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
|
||||||
|
@NotNull Object source, @NotNull Type typeInstance) throws Exception {
|
||||||
|
Class<?> rawType = type.getRawType();
|
||||||
|
|
||||||
|
if (rawType.isArray()) {
|
||||||
|
return deserializeArray(holder, type, source, rawType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeInstance instanceof ParameterizedType) {
|
||||||
|
return deserializeParameterized(holder, type, source, (ParameterizedType) typeInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("No adapter for type " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T deserializeArray(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
|
||||||
|
@NotNull Object source, @NotNull Class<?> rawType) throws Exception {
|
||||||
|
List<?> list;
|
||||||
|
if (source instanceof List<?>) {
|
||||||
|
list = (List<?>) source;
|
||||||
|
} else {
|
||||||
|
// For non-list sources, treat as single element array
|
||||||
|
list = Collections.singletonList(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = list.size();
|
||||||
|
if (size == 0) {
|
||||||
|
return type.cast(Array.newInstance(rawType.getComponentType(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> componentType = rawType.getComponentType();
|
||||||
|
Object[] array = (Object[]) Array.newInstance(componentType, size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
array[i] = deserialize(holder, componentType, list.get(i));
|
||||||
|
}
|
||||||
|
return type.cast(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> T deserializeParameterized(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
|
||||||
|
@NotNull Object source, @NotNull ParameterizedType pt) throws Exception {
|
||||||
|
Type rawType = pt.getRawType();
|
||||||
|
Type[] typeArgs = pt.getActualTypeArguments();
|
||||||
|
|
||||||
|
if (rawType == List.class || rawType == Collection.class || rawType == ArrayList.class) {
|
||||||
|
return (T) deserializeCollection(holder, source, typeArgs[0], ArrayList::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawType == Set.class || rawType == HashSet.class) {
|
||||||
|
return (T) deserializeCollection(holder, source, typeArgs[0], HashSet::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawType == Map.class || rawType == LinkedHashMap.class) {
|
||||||
|
return (T) deserializeMap(holder, source, typeArgs[0], typeArgs[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("No adapter for parameterized type " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<?> deserializeCollection(@NotNull ConfigurationHolder<?> holder, @NotNull Object source,
|
||||||
|
@NotNull Type elementType, @NotNull java.util.function.Supplier<Collection<Object>> collectionFactory) throws Exception {
|
||||||
|
ValueType<?> elementValueType = ValueType.of(elementType);
|
||||||
|
List<?> sourceList = deserializeList(holder, elementValueType, source);
|
||||||
|
|
||||||
|
if (sourceList.isEmpty()) {
|
||||||
|
return collectionFactory.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<Object> result = collectionFactory.get();
|
||||||
|
if (result instanceof ArrayList) {
|
||||||
|
((ArrayList<Object>) result).ensureCapacity(sourceList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object item : sourceList) {
|
||||||
|
Object deserializedItem = deserialize(holder, elementValueType, item);
|
||||||
|
if (deserializedItem != null) {
|
||||||
|
result.add(deserializedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Object, Object> deserializeMap(@NotNull ConfigurationHolder<?> holder, @NotNull Object source,
|
||||||
|
@NotNull Type keyType, @NotNull Type valueType) throws Exception {
|
||||||
|
Map<?, ?> sourceMap;
|
||||||
|
if (source instanceof Map<?, ?>) {
|
||||||
|
sourceMap = (Map<?, ?>) source;
|
||||||
|
} else if (source instanceof ConfigureSection) {
|
||||||
|
sourceMap = ((ConfigureSection) source).asMap();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Cannot deserialize to Map from " + source.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
int mapSize = sourceMap.size();
|
||||||
|
if (mapSize == 0) {
|
||||||
|
return new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType<?> keyValueType = ValueType.of(keyType);
|
||||||
|
ValueType<?> valueValueType = ValueType.of(valueType);
|
||||||
|
Map<Object, Object> resultMap = new LinkedHashMap<>(mapSize);
|
||||||
|
|
||||||
|
for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {
|
||||||
|
Object key = deserialize(holder, keyValueType, entry.getKey());
|
||||||
|
Object value = deserialize(holder, valueValueType, entry.getValue());
|
||||||
|
resultMap.put(key, value);
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public <T> Object serialize(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception {
|
public <T> Object serialize(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception {
|
||||||
if (value == null) return null; // Null check
|
if (value == null) return null; // Null check
|
||||||
|
|
||||||
ValueType<T> type = ValueType.of(value);
|
ValueType<T> type = ValueType.of(value);
|
||||||
ValueAdapter<T> adapter = adapterOf(type);
|
ValueAdapter<T> adapter = adapterOf(type);
|
||||||
if (adapter == null) return value; // No adapters, try to return the original value
|
if (adapter != null) return adapter.serialize(holder, type, value);
|
||||||
return adapter.serialize(holder, type, value);
|
|
||||||
|
if (value.getClass().isArray()) {
|
||||||
|
Object[] array = (Object[]) value;
|
||||||
|
List<Object> serializedList = new ArrayList<>(array.length);
|
||||||
|
for (Object item : array) {
|
||||||
|
serializedList.add(serialize(holder, item));
|
||||||
|
}
|
||||||
|
return serializedList;
|
||||||
|
} else if (value instanceof Collection<?>) {
|
||||||
|
Collection<?> collection = (Collection<?>) value;
|
||||||
|
List<Object> serializedList = new ArrayList<>(collection.size());
|
||||||
|
for (Object item : collection) {
|
||||||
|
serializedList.add(serialize(holder, item));
|
||||||
|
}
|
||||||
|
return serializedList;
|
||||||
|
} else if (value instanceof Map<?, ?>) {
|
||||||
|
Map<?, ?> map = (Map<?, ?>) value;
|
||||||
|
Map<Object, Object> serializedMap = new LinkedHashMap<>(map.size());
|
||||||
|
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||||
|
Object key = serialize(holder, entry.getKey());
|
||||||
|
Object val = serialize(holder, entry.getValue());
|
||||||
|
serializedMap.put(key, val);
|
||||||
|
}
|
||||||
|
return serializedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value; // No adapters, and cannot handle, try to return the original value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected <T> List<T> deserializeList(@NotNull ConfigurationHolder<?> holder,
|
||||||
|
@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
||||||
|
if (source == null) return Collections.emptyList(); // Null check
|
||||||
|
if (source instanceof List<?>) {
|
||||||
|
List<?> list = (List<?>) source;
|
||||||
|
List<T> result = new ArrayList<>(list.size());
|
||||||
|
for (Object item : list) {
|
||||||
|
T deserializedItem = deserialize(holder, type, item);
|
||||||
|
if (deserializedItem != null) {
|
||||||
|
result.add(deserializedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else { // Maybe singleton? Let's try to deserialize it as a single element list
|
||||||
|
T deserializedItem = deserialize(holder, type, source);
|
||||||
|
if (deserializedItem != null) {
|
||||||
|
return Collections.singletonList(deserializedItem);
|
||||||
|
} else return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value deserializer, convert base data to target value.
|
* Value deserializer, convert base data to target value.
|
||||||
@@ -11,9 +12,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ValueParser<TYPE> {
|
public interface ValueParser<TYPE> {
|
||||||
|
|
||||||
TYPE parse(
|
@Nullable TYPE parse(
|
||||||
@NotNull ConfigurationHolder<?> holder,
|
@NotNull ConfigurationHolder<?> holder,
|
||||||
@NotNull ValueType<? super TYPE> type, @NotNull Object data
|
@NotNull ValueType<? super TYPE> type, @NotNull Object data
|
||||||
) throws Exception;
|
) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value serializer, convert target value to base data.
|
* Value serializer, convert target value to base data.
|
||||||
@@ -11,9 +12,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ValueSerializer<TYPE> {
|
public interface ValueSerializer<TYPE> {
|
||||||
|
|
||||||
Object serialize(
|
@Nullable Object serialize(
|
||||||
@NotNull ConfigurationHolder<?> holder,
|
@NotNull ConfigurationHolder<?> holder,
|
||||||
@NotNull ValueType<? super TYPE> type, @NotNull TYPE value
|
@NotNull ValueType<? super TYPE> type, @NotNull TYPE value
|
||||||
) throws Exception;
|
) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
package cc.carm.lib.configuration.adapter;
|
package cc.carm.lib.configuration.adapter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to get the generic type.
|
* {@link ValueType} used to get the generic type of the value,
|
||||||
|
* It can be used to check if an object is an instance of a specific type,
|
||||||
|
* and to cast objects to the correct type.
|
||||||
|
* <p>
|
||||||
|
* Java's type system is not capable of retaining generic type information at runtime.
|
||||||
|
* This class is used to represent a type with its generic parameters.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public abstract class ValueType<T> {
|
public abstract class ValueType<T> {
|
||||||
|
|
||||||
|
public static final ValueType<Object> OBJECT = ofPrimitiveType(Object.class);
|
||||||
public static final ValueType<String> STRING = ofPrimitiveType(String.class);
|
public static final ValueType<String> STRING = ofPrimitiveType(String.class);
|
||||||
public static final ValueType<Integer> INTEGER = ofPrimitiveType(Integer.class);
|
public static final ValueType<Integer> INTEGER = ofPrimitiveType(Integer.class);
|
||||||
public static final ValueType<Integer> INTEGER_TYPE = ofPrimitiveType(int.class);
|
public static final ValueType<Integer> INTEGER_TYPE = ofPrimitiveType(int.class);
|
||||||
@@ -31,8 +40,8 @@ public abstract class ValueType<T> {
|
|||||||
public static final ValueType<Character> CHAR_TYPE = ofPrimitiveType(char.class);
|
public static final ValueType<Character> CHAR_TYPE = ofPrimitiveType(char.class);
|
||||||
|
|
||||||
public static final ValueType<?>[] PRIMITIVE_TYPES = {
|
public static final ValueType<?>[] PRIMITIVE_TYPES = {
|
||||||
STRING, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, BYTE, SHORT, CHAR,
|
STRING, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, BYTE, SHORT, CHAR,
|
||||||
INTEGER_TYPE, LONG_TYPE, DOUBLE_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE
|
INTEGER_TYPE, LONG_TYPE, DOUBLE_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -43,7 +52,7 @@ public abstract class ValueType<T> {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> ValueType<T> of(final Type type) {
|
public static <T> ValueType<T> of(final Type type) {
|
||||||
if (type == null) throw new NullPointerException("Type cannot be null");
|
if (type == null) throw new NullPointerException("Type cannot be null");
|
||||||
if (type instanceof Class<?>) { // Try handle primitive types
|
if (type instanceof Class<?>) { // Try to fast handle primitive types
|
||||||
Class<?> clazz = (Class<?>) type;
|
Class<?> clazz = (Class<?>) type;
|
||||||
for (ValueType<?> valueType : PRIMITIVE_TYPES) {
|
for (ValueType<?> valueType : PRIMITIVE_TYPES) {
|
||||||
if (valueType.getRawType() == clazz) {
|
if (valueType.getRawType() == clazz) {
|
||||||
@@ -55,10 +64,26 @@ public abstract class ValueType<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ValueType<T> of(final Class<T> clazz) {
|
public static <T> ValueType<T> of(final @NotNull Class<T> clazz) {
|
||||||
return of((Type) clazz);
|
return of((Type) clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> ValueType<List<T>> ofList(final @NotNull Class<T> paramType) {
|
||||||
|
return of(List.class, paramType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ValueType<List<T>> ofList(final @NotNull ValueType<T> paramType) {
|
||||||
|
return of(List.class, paramType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> ValueType<Map<K, V>> ofMap(final @NotNull Class<K> keyType, final @NotNull Class<V> valueType) {
|
||||||
|
return of(Map.class, keyType, valueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> ValueType<Map<K, V>> ofMap(final @NotNull ValueType<K> keyType, final @NotNull ValueType<V> valueType) {
|
||||||
|
return of(Map.class, keyType.getType(), valueType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the generic type of the complex type.
|
* Get the generic type of the complex type.
|
||||||
*
|
*
|
||||||
@@ -87,6 +112,7 @@ public abstract class ValueType<T> {
|
|||||||
return of(parameterizedType);
|
return of(parameterizedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
private static <T> ValueType<T> ofPrimitiveType(Class<T> clazz) {
|
private static <T> ValueType<T> ofPrimitiveType(Class<T> clazz) {
|
||||||
return new ValueType<T>(clazz) {
|
return new ValueType<T>(clazz) {
|
||||||
};
|
};
|
||||||
@@ -106,40 +132,65 @@ public abstract class ValueType<T> {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this ValueType is a subtype of the given Class.
|
||||||
|
*
|
||||||
|
* @param target The target Class to check against
|
||||||
|
* @return true if this ValueType is a subtype of the target Class, false otherwise
|
||||||
|
*/
|
||||||
public boolean isSubtypeOf(Class<?> target) {
|
public boolean isSubtypeOf(Class<?> target) {
|
||||||
Class<?> rawType = getRawType();
|
Class<?> rawType = getRawType();
|
||||||
return target.isAssignableFrom(rawType);
|
return target.isAssignableFrom(rawType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this ValueType is a subtype of the given ValueType.
|
||||||
|
*
|
||||||
|
* @param target The target ValueType to check against
|
||||||
|
* @return true if this ValueType is a subtype of the target, false otherwise
|
||||||
|
*/
|
||||||
public boolean isSubtypeOf(ValueType<?> target) {
|
public boolean isSubtypeOf(ValueType<?> target) {
|
||||||
return target.isSubtypeOf(getRawType());
|
return target.isSubtypeOf(getRawType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given object is an instance of the type represented by this ValueType.
|
||||||
|
*
|
||||||
|
* @param obj The object to check
|
||||||
|
* @return true if the object is an instance of the type, false otherwise
|
||||||
|
*/
|
||||||
public boolean isInstance(Object obj) {
|
public boolean isInstance(Object obj) {
|
||||||
return obj != null && getRawType().isInstance(obj);
|
return obj != null && getRawType().isInstance(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提取当前 ValueType 的原始类型(Class 对象)。
|
* Extracts the raw type from the generic type.
|
||||||
*
|
*
|
||||||
* @return 对应的 Class 对象
|
* @return The raw type of the generic type
|
||||||
* @throws IllegalStateException 如果无法提取出原始类型
|
* @throws IllegalStateException if the type is not a Class or ParameterizedType
|
||||||
*/
|
*/
|
||||||
public Class<?> getRawType() {
|
@SuppressWarnings("unchecked")
|
||||||
|
public Class<T> getRawType() {
|
||||||
if (type instanceof Class<?>) {
|
if (type instanceof Class<?>) {
|
||||||
return (Class<?>) type;
|
return (Class<T>) type;
|
||||||
}
|
}
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
ParameterizedType pt = (ParameterizedType) type;
|
ParameterizedType pt = (ParameterizedType) type;
|
||||||
Type raw = pt.getRawType();
|
Type raw = pt.getRawType();
|
||||||
if (raw instanceof Class<?>) {
|
if (raw instanceof Class<?>) {
|
||||||
return (Class<?>) raw;
|
return (Class<T>) raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unsupported type: " + type);
|
throw new IllegalStateException("Unsupported type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts the object to the type represented by this ValueType.
|
||||||
|
*
|
||||||
|
* @param obj The object to cast
|
||||||
|
* @return The object cast to the type represented by this ValueType
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T cast(Object obj) {
|
public T cast(Object obj) {
|
||||||
if (!isInstance(obj)) {
|
if (!isInstance(obj)) {
|
||||||
@@ -148,6 +199,12 @@ public abstract class ValueType<T> {
|
|||||||
return (T) obj;
|
return (T) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the type.
|
||||||
|
* Like "{@code java.util.List<java.lang.String>}" or "java.lang.Integer".
|
||||||
|
*
|
||||||
|
* @return String representation of the type
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (type instanceof Class<?>) {
|
if (type instanceof Class<?>) {
|
||||||
@@ -157,7 +214,7 @@ public abstract class ValueType<T> {
|
|||||||
ParameterizedType pt = (ParameterizedType) type;
|
ParameterizedType pt = (ParameterizedType) type;
|
||||||
Type raw = pt.getRawType();
|
Type raw = pt.getRawType();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(raw.getTypeName());
|
sb.append(raw.getClass().getName());
|
||||||
sb.append('<');
|
sb.append('<');
|
||||||
Type[] args = pt.getActualTypeArguments();
|
Type[] args = pt.getActualTypeArguments();
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
@@ -166,6 +223,7 @@ public abstract class ValueType<T> {
|
|||||||
}
|
}
|
||||||
sb.append(args[i].getTypeName());
|
sb.append(args[i].getTypeName());
|
||||||
}
|
}
|
||||||
|
sb.append('>');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
return type.getTypeName();
|
return type.getTypeName();
|
||||||
|
|||||||
+2
-2
@@ -11,11 +11,11 @@ import java.util.Arrays;
|
|||||||
public class PrimitiveAdapter<T> extends ValueAdapter<T> {
|
public class PrimitiveAdapter<T> extends ValueAdapter<T> {
|
||||||
|
|
||||||
public static final String[] TRUE_VALUES = new String[]{
|
public static final String[] TRUE_VALUES = new String[]{
|
||||||
"true", "yes", "on", "1", "enabled", "enable", "active"
|
"true", "yes", "on", "1", "enabled", "enable", "active"
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final String[] FALSE_VALUES = new String[]{
|
public static final String[] FALSE_VALUES = new String[]{
|
||||||
"false", "no", "off", "0", "disabled", "disable", "inactive"
|
"false", "no", "off", "0", "disabled", "disable", "inactive"
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
|||||||
+18
-10
@@ -5,26 +5,34 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
|||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter.*;
|
import static cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter.*;
|
||||||
|
|
||||||
public interface StandardAdapters {
|
public interface StandardAdapters {
|
||||||
|
|
||||||
@NotNull PrimitiveAdapter<?>[] PRIMITIVES = new PrimitiveAdapter[]{
|
@NotNull PrimitiveAdapter<?>[] PRIMITIVES = new PrimitiveAdapter[]{
|
||||||
ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(),
|
ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(),
|
||||||
ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(),
|
ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(),
|
||||||
ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType()
|
ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType()
|
||||||
};
|
};
|
||||||
|
|
||||||
@NotNull ValueAdapter<Enum<?>> ENUMS = PrimitiveAdapter.ofEnum();
|
@NotNull ValueAdapter<Enum<?>> ENUMS = PrimitiveAdapter.ofEnum();
|
||||||
|
|
||||||
|
@NotNull ValueAdapter<UUID> UUID = new ValueAdapter<>(
|
||||||
|
ValueType.of(UUID.class),
|
||||||
|
(provider, type, value) -> value.toString(),
|
||||||
|
(provider, type, value) -> java.util.UUID.fromString(value.toString())
|
||||||
|
);
|
||||||
|
|
||||||
@NotNull ValueAdapter<ConfigureSection> SECTIONS = new ValueAdapter<>(
|
@NotNull ValueAdapter<ConfigureSection> SECTIONS = new ValueAdapter<>(
|
||||||
ValueType.of(ConfigureSection.class),
|
ValueType.of(ConfigureSection.class),
|
||||||
(provider, type, value) -> value,
|
(provider, type, value) -> value,
|
||||||
(provider, type, value) -> {
|
(provider, type, value) -> {
|
||||||
if (value instanceof ConfigureSection) {
|
if (value instanceof ConfigureSection) {
|
||||||
return (ConfigureSection) value;
|
return (ConfigureSection) value;
|
||||||
} else throw new IllegalArgumentException("Value is not a ConfigurationSection");
|
} else throw new IllegalArgumentException("Value is not a ConfigurationSection");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package cc.carm.lib.configuration.builder;
|
package cc.carm.lib.configuration.builder;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.function.DataValidator;
|
||||||
|
import cc.carm.lib.configuration.function.ValueValidator;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
@@ -11,12 +13,13 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class AbstractConfigBuilder<
|
public abstract class AbstractConfigBuilder<
|
||||||
TYPE, RESULT extends ConfigValue<TYPE>, HOLDER extends ConfigurationHolder<?>,
|
TYPE, UNIT, RESULT extends ConfigValue<TYPE, UNIT>, HOLDER extends ConfigurationHolder<?>,
|
||||||
SELF extends AbstractConfigBuilder<TYPE, RESULT, HOLDER, SELF>
|
SELF extends AbstractConfigBuilder<TYPE, UNIT, RESULT, HOLDER, SELF>
|
||||||
> {
|
> {
|
||||||
|
|
||||||
protected final Class<? super HOLDER> providerClass;
|
protected final Class<? super HOLDER> providerClass;
|
||||||
protected final ValueType<TYPE> type;
|
protected final ValueType<TYPE> type;
|
||||||
@@ -24,6 +27,7 @@ public abstract class AbstractConfigBuilder<
|
|||||||
protected @Nullable HOLDER holder;
|
protected @Nullable HOLDER holder;
|
||||||
protected @Nullable String path;
|
protected @Nullable String path;
|
||||||
|
|
||||||
|
protected @NotNull ValueValidator<UNIT> valueValidator = ValueValidator.none();
|
||||||
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
|
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
|
||||||
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> {
|
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> {
|
||||||
};
|
};
|
||||||
@@ -37,54 +41,121 @@ public abstract class AbstractConfigBuilder<
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract @NotNull SELF self();
|
protected abstract SELF self();
|
||||||
|
|
||||||
public abstract @NotNull RESULT build();
|
public abstract @NotNull RESULT build();
|
||||||
|
|
||||||
public @NotNull SELF holder(@Nullable HOLDER holder) {
|
public SELF holder(@Nullable HOLDER holder) {
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF path(@Nullable String path) {
|
public SELF path(@Nullable String path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
/**
|
||||||
|
* Set the {@link ValueValidator} for the value.
|
||||||
|
*
|
||||||
|
* @param validator The validator to set.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validator(@NotNull ValueValidator<UNIT> validator) {
|
||||||
|
this.valueValidator = validator;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link DataValidator} for the value.
|
||||||
|
*
|
||||||
|
* @param validator The validator to set.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validator(@NotNull DataValidator<? super UNIT> validator) {
|
||||||
|
return validator((h, value) -> validator.validate(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the value with the specified condition.
|
||||||
|
*
|
||||||
|
* @param validator The validator to append.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validate(@NotNull ValueValidator<? super UNIT> validator) {
|
||||||
|
return validator(this.valueValidator.and(validator));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the value with the specified condition.
|
||||||
|
*
|
||||||
|
* @param validator The validator to append.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validate(@NotNull DataValidator<? super UNIT> validator) {
|
||||||
|
return validate((h, value) -> validator.validate(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the value with the specified condition.
|
||||||
|
*
|
||||||
|
* @param condition The condition to check, if the condition is false, an exception will be thrown.
|
||||||
|
* @param exception The exception to throw if the condition is false.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull Exception exception) {
|
||||||
|
return validate((h, value) -> {
|
||||||
|
if (!condition.test(value)) throw exception;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the value with the specified condition.
|
||||||
|
*
|
||||||
|
* @param condition The condition to check, if the condition is false, an exception will be thrown.
|
||||||
|
* @param msg The message to throw if the condition is false.
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull String msg) {
|
||||||
|
return validate((h, value) -> {
|
||||||
|
if (!condition.test(value)) throw new IllegalArgumentException(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
public SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||||
return initializer(initializer.andThen(initializer));
|
return initializer(initializer.andThen(initializer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
|
public SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
|
||||||
return append((provider, valuePath) -> initializer.accept(provider));
|
return append((provider, valuePath) -> initializer.accept(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF defaults(@Nullable TYPE defaultValue) {
|
public SELF defaults(@Nullable TYPE defaultValue) {
|
||||||
return defaults(() -> defaultValue);
|
return defaults(() -> defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
|
public SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
|
||||||
this.defaultValueSupplier = supplier;
|
this.defaultValueSupplier = supplier;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <M> @NotNull SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
|
public SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
|
||||||
return append((h, p) -> metaConsumer.accept(h.metadata(p)));
|
return append((h, p) -> metaConsumer.accept(h.metadata(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <M> @NotNull SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
|
public <M> SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
|
||||||
return meta(h -> h.set(type, value));
|
return meta(h -> h.set(type, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @NotNull ValueManifest<TYPE> buildManifest() {
|
protected @NotNull ValueManifest<TYPE, UNIT> buildManifest() {
|
||||||
return new ValueManifest<>(
|
return new ValueManifest<>(
|
||||||
type(), this.defaultValueSupplier, this.initializer,
|
type(), this.defaultValueSupplier, this.valueValidator,
|
||||||
this.holder, this.path
|
this.initializer, this.holder, this.path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
|||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
|
|
||||||
public abstract class CommonConfigBuilder<TYPE, RESULT extends ConfigValue<TYPE>, SELF extends CommonConfigBuilder<TYPE, RESULT, SELF>>
|
public abstract class CommonConfigBuilder<
|
||||||
extends AbstractConfigBuilder<TYPE, RESULT, ConfigurationHolder<?>, SELF> {
|
TYPE, UNIT,
|
||||||
|
RESULT extends ConfigValue<TYPE, UNIT>,
|
||||||
|
SELF extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF>
|
||||||
|
> extends AbstractConfigBuilder<TYPE, UNIT, RESULT, ConfigurationHolder<?>, SELF> {
|
||||||
|
|
||||||
protected CommonConfigBuilder(ValueType<TYPE> type) {
|
protected CommonConfigBuilder(ValueType<TYPE> type) {
|
||||||
super(ConfigurationHolder.class, type);
|
super(ConfigurationHolder.class, type);
|
||||||
|
|||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package cc.carm.lib.configuration.builder.collection;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
||||||
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public abstract class SectionCollectionBuilder<
|
||||||
|
V, C extends Collection<V>,
|
||||||
|
RESULT extends CollectionConfigValue<V, C, ?>,
|
||||||
|
SELF extends SectionCollectionBuilder<V, C, RESULT, SELF>
|
||||||
|
> extends AbstractSectionBuilder<C, V, RESULT, SELF> {
|
||||||
|
|
||||||
|
protected @NotNull Supplier<? extends C> constructor;
|
||||||
|
|
||||||
|
public SectionCollectionBuilder(@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<ConfigureSection, V> parser,
|
||||||
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
|
||||||
|
super(new ValueType<C>() {
|
||||||
|
}, paramType, parser, serializer);
|
||||||
|
this.constructor = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public final @NotNull SELF defaults(@NotNull V... values) {
|
||||||
|
return defaults(c -> c.addAll(Arrays.asList(values)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final @NotNull SELF defaults(@NotNull Consumer<C> constructor) {
|
||||||
|
return defaults(() -> {
|
||||||
|
C collection = this.constructor.get();
|
||||||
|
constructor.accept(collection);
|
||||||
|
return collection;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF constructor(@NotNull Supplier<? extends C> constructor) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF construct(@NotNull C collection) {
|
||||||
|
return constructor(() -> collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
package cc.carm.lib.configuration.builder.collection;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
|
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class SimpleCollectionCreator<V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>> {
|
||||||
|
|
||||||
|
public static <V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
|
||||||
|
@NotNull SimpleCollectionCreator<V, C, RESULT> create(
|
||||||
|
@NotNull ValueType<V> type,
|
||||||
|
@NotNull Supplier<? extends C> defaultConstructor,
|
||||||
|
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
|
||||||
|
return new SimpleCollectionCreator<>(type, defaultConstructor, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @NotNull Supplier<? extends C> defaultConstructor;
|
||||||
|
protected final @NotNull ValueType<V> type;
|
||||||
|
|
||||||
|
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
|
||||||
|
|
||||||
|
public SimpleCollectionCreator(@NotNull ValueType<V> type,
|
||||||
|
@NotNull Supplier<? extends C> defaultConstructor,
|
||||||
|
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
|
||||||
|
this.defaultConstructor = defaultConstructor;
|
||||||
|
this.type = type;
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S> @NotNull Source<S, V, C, RESULT> from(@NotNull Class<S> sourceType) {
|
||||||
|
return from(ValueType.of(sourceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S> @NotNull Source<S, V, C, RESULT> from(@NotNull ValueType<S> sourceType) {
|
||||||
|
return new Source<S, V, C, RESULT>(
|
||||||
|
defaultConstructor, sourceType, type,
|
||||||
|
ValueHandler.required(type),
|
||||||
|
ValueHandler.required(sourceType),
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SimpleCollectionCreator.Source<Object, V, C, RESULT> fromObject() {
|
||||||
|
return new Source<Object, V, C, RESULT>(
|
||||||
|
defaultConstructor, ValueType.OBJECT, type,
|
||||||
|
ValueHandler.deserialize(type), ValueHandler.toObject(),
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SimpleCollectionCreator.Source<String, V, C, RESULT> fromString() {
|
||||||
|
return new Source<String, V, C, RESULT>(
|
||||||
|
defaultConstructor, ValueType.STRING, type,
|
||||||
|
ValueHandler.required(type), ValueHandler.stringValue(),
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SimpleCollectionCreator.Section<V, C, RESULT> fromSection() {
|
||||||
|
return new Section<V, C, RESULT>(
|
||||||
|
defaultConstructor, type,
|
||||||
|
ValueHandler.required(type), ValueHandler.required(),
|
||||||
|
factory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CollectionValueFactory<V, C, RESULT> {
|
||||||
|
@NotNull RESULT build(
|
||||||
|
@NotNull ValueManifest<C, V> manifest,
|
||||||
|
@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueAdapter<V> paramAdapter
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Source<SOURCE, V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
|
||||||
|
extends SourceCollectionBuilder<SOURCE, V, C, RESULT, Source<SOURCE, V, C, RESULT>> {
|
||||||
|
|
||||||
|
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
|
||||||
|
|
||||||
|
public Source(
|
||||||
|
@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueType<SOURCE> sourceType,
|
||||||
|
@NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<SOURCE, V> parser,
|
||||||
|
@NotNull ValueHandler<V, SOURCE> serializer,
|
||||||
|
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
|
||||||
|
super(constructor, sourceType, paramType, parser, serializer);
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull SimpleCollectionCreator.Source<SOURCE, V, C, RESULT> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull RESULT build() {
|
||||||
|
return factory.build(buildManifest(), constructor, buildAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Section<V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
|
||||||
|
extends SectionCollectionBuilder<V, C, RESULT, Section<V, C, RESULT>> {
|
||||||
|
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
|
||||||
|
|
||||||
|
public Section(
|
||||||
|
@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<ConfigureSection, V> parser,
|
||||||
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer,
|
||||||
|
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
|
||||||
|
super(constructor, paramType, parser, serializer);
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull SimpleCollectionCreator.Section<V, C, RESULT> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull RESULT build() {
|
||||||
|
return factory.build(buildManifest(), constructor, buildAdapter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
package cc.carm.lib.configuration.builder.collection;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
||||||
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
|
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public abstract class SourceCollectionBuilder<
|
||||||
|
SOURCE, V, C extends Collection<V>,
|
||||||
|
RESULT extends CollectionConfigValue<V, C, ?>,
|
||||||
|
SELF extends SourceCollectionBuilder<SOURCE, V, C, RESULT, SELF>
|
||||||
|
>
|
||||||
|
extends AbstractSourceBuilder<C, SOURCE, V, RESULT, SELF> {
|
||||||
|
|
||||||
|
protected @NotNull Supplier<? extends C> constructor;
|
||||||
|
|
||||||
|
public SourceCollectionBuilder(@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<SOURCE, V> parser, @NotNull ValueHandler<V, SOURCE> serializer) {
|
||||||
|
super(new ValueType<C>() {
|
||||||
|
}, sourceType, paramType, parser, serializer);
|
||||||
|
this.constructor = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public final @NotNull SELF defaults(@NotNull V... values) {
|
||||||
|
return defaults(c -> c.addAll(Arrays.asList(values)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final @NotNull SELF defaults(@NotNull Consumer<C> constructor) {
|
||||||
|
return defaults(() -> {
|
||||||
|
C collection = this.constructor.get();
|
||||||
|
constructor.accept(collection);
|
||||||
|
return collection;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF constructor(@NotNull Supplier<? extends C> constructor) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF construct(@NotNull C collection) {
|
||||||
|
return constructor(() -> collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+27
-29
@@ -4,7 +4,7 @@ import cc.carm.lib.configuration.adapter.ValueAdapter;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.function.ValueConsumer;
|
import cc.carm.lib.configuration.function.ValueComposer;
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
@@ -14,47 +14,45 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class AbstractSectionBuilder<
|
public abstract class AbstractSectionBuilder<
|
||||||
TYPE, PARAM,
|
TYPE, UNIT,
|
||||||
RESULT extends ConfigValue<TYPE>,
|
RESULT extends ConfigValue<TYPE, UNIT>,
|
||||||
SELF extends AbstractSectionBuilder<TYPE, PARAM, RESULT, SELF>
|
SELF extends AbstractSectionBuilder<TYPE, UNIT, RESULT, SELF>
|
||||||
> extends CommonConfigBuilder<TYPE, RESULT, SELF> {
|
> extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF> {
|
||||||
|
|
||||||
|
|
||||||
protected final @NotNull ValueType<PARAM> paramType;
|
protected final @NotNull ValueType<UNIT> paramType;
|
||||||
|
|
||||||
protected @NotNull ValueHandler<ConfigureSection, PARAM> parser;
|
protected @NotNull ValueHandler<ConfigureSection, UNIT> parser;
|
||||||
protected @NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer;
|
protected @NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer;
|
||||||
|
|
||||||
protected AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
protected AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<UNIT> paramType,
|
||||||
@NotNull ValueHandler<ConfigureSection, PARAM> parser,
|
@NotNull ValueHandler<ConfigureSection, UNIT> parser,
|
||||||
@NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
|
||||||
super(type);
|
super(type);
|
||||||
this.paramType = paramType;
|
this.paramType = paramType;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, PARAM> valueParser) {
|
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, UNIT> valueParser) {
|
||||||
return parse((p, section) -> valueParser.handle(section));
|
return parse((p, section) -> valueParser.handle(section));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, PARAM> valueParser) {
|
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, UNIT> valueParser) {
|
||||||
this.parser = valueParser;
|
this.parser = valueParser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, ? extends Map<String, Object>> serializer) {
|
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, ? extends Map<String, Object>> serializer) {
|
||||||
return serialize((p, value) -> {
|
return serialize((p, value) -> serializer.handle(value));
|
||||||
return serializer.handle(value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull ValueConsumer<Map<String, Object>, PARAM> serializer) {
|
public @NotNull SELF serialize(@NotNull ValueComposer<Map<String, Object>, UNIT> serializer) {
|
||||||
return serialize((h, value) -> {
|
return serialize((h, value) -> {
|
||||||
Map<String, Object> map = new LinkedHashMap<>();
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
serializer.accept(h, map, value);
|
serializer.accept(h, map, value);
|
||||||
@@ -62,17 +60,17 @@ public abstract class AbstractSectionBuilder<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueAdapter<PARAM> buildAdapter() {
|
protected ValueAdapter<UNIT> buildAdapter() {
|
||||||
return new ValueAdapter<>(this.paramType)
|
return new ValueAdapter<>(this.paramType)
|
||||||
.parser((p, type, data) -> {
|
.parser((p, type, data) -> {
|
||||||
ConfigureSection section = p.deserialize(ConfigureSection.class, data);
|
ConfigureSection section = p.deserialize(ConfigureSection.class, data);
|
||||||
if (section == null) return null;
|
if (section == null) return null;
|
||||||
return this.parser.handle(p, section);
|
return this.parser.handle(p, section);
|
||||||
})
|
})
|
||||||
.serializer((p, type, data) -> {
|
.serializer((p, type, data) -> {
|
||||||
Map<String, Object> map = this.serializer.handle(p, data);
|
Map<String, Object> map = this.serializer.handle(p, data);
|
||||||
return map == null || map.isEmpty() ? null : map;
|
return map == null || map.isEmpty() ? null : map;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-28
@@ -1,6 +1,8 @@
|
|||||||
package cc.carm.lib.configuration.builder.impl;
|
package cc.carm.lib.configuration.builder.impl;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueParser;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
@@ -9,54 +11,63 @@ import cc.carm.lib.configuration.value.ConfigValue;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public abstract class AbstractSourceBuilder<
|
public abstract class AbstractSourceBuilder<
|
||||||
V, SOURCE, PARAM, RESULT extends ConfigValue<V>,
|
V, SOURCE, UNIT, RESULT extends ConfigValue<V, UNIT>,
|
||||||
SELF extends AbstractSourceBuilder<V, SOURCE, PARAM, RESULT, SELF>
|
SELF extends AbstractSourceBuilder<V, SOURCE, UNIT, RESULT, SELF>
|
||||||
> extends CommonConfigBuilder<V, RESULT, SELF> {
|
> extends CommonConfigBuilder<V, UNIT, RESULT, SELF> {
|
||||||
|
|
||||||
protected final @NotNull ValueType<SOURCE> sourceType;
|
protected final @NotNull ValueType<SOURCE> sourceType;
|
||||||
protected final @NotNull ValueType<PARAM> paramType;
|
protected final @NotNull ValueType<UNIT> paramType;
|
||||||
protected @NotNull ValueHandler<SOURCE, PARAM> valueParser;
|
|
||||||
protected @NotNull ValueHandler<PARAM, SOURCE> valueSerializer;
|
@SuppressWarnings("NotNullFieldNotInitialized") // Already initialized in constructor
|
||||||
|
protected @NotNull ValueParser<UNIT> valueParser;
|
||||||
|
@SuppressWarnings("NotNullFieldNotInitialized") // Already initialized in constructor
|
||||||
|
protected @NotNull ValueSerializer<UNIT> valueSerializer;
|
||||||
|
|
||||||
protected AbstractSourceBuilder(@NotNull ValueType<V> type,
|
protected AbstractSourceBuilder(@NotNull ValueType<V> type,
|
||||||
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<PARAM> paramType,
|
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<UNIT> paramType,
|
||||||
@NotNull ValueHandler<SOURCE, PARAM> parser,
|
@NotNull ValueHandler<SOURCE, UNIT> parser,
|
||||||
@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
@NotNull ValueHandler<UNIT, SOURCE> serializer) {
|
||||||
super(type);
|
super(type);
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
this.paramType = paramType;
|
this.paramType = paramType;
|
||||||
this.valueParser = parser;
|
parse(parser);
|
||||||
this.valueSerializer = serializer;
|
serialize(serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, PARAM> parser) {
|
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, UNIT> parser) {
|
||||||
return parse((p, source) -> parser.handle(source));
|
return parse((p, source) -> parser.handle(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, PARAM> parser) {
|
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, UNIT> parser) {
|
||||||
|
return parser((holder, type, data) -> {
|
||||||
|
SOURCE source = holder.deserialize(this.sourceType, data);
|
||||||
|
return parser.handle(holder, source);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF parser(@NotNull ValueParser<UNIT> parser) {
|
||||||
this.valueParser = parser;
|
this.valueParser = parser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, SOURCE> serializer) {
|
||||||
|
return serializer((holder, type, data) -> {
|
||||||
|
SOURCE source = serializer.handle(holder, data);
|
||||||
|
return holder.serialize(source);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, SOURCE> serializer) {
|
||||||
|
return serialize((p, value) -> serializer.handle(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF serializer(@NotNull ValueSerializer<UNIT> serializer) {
|
||||||
this.valueSerializer = serializer;
|
this.valueSerializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, SOURCE> serializer) {
|
protected ValueAdapter<UNIT> buildAdapter() {
|
||||||
return serialize((p, value) -> serializer.handle(value));
|
return new ValueAdapter<>(this.paramType, this.valueSerializer, this.valueParser);
|
||||||
}
|
|
||||||
|
|
||||||
protected ValueAdapter<PARAM> buildAdapter() {
|
|
||||||
return new ValueAdapter<>(this.paramType)
|
|
||||||
.parser((holder, type, data) -> {
|
|
||||||
SOURCE source = holder.deserialize(this.sourceType, data);
|
|
||||||
return this.valueParser.handle(holder, source);
|
|
||||||
})
|
|
||||||
.serializer((holder, type, data) -> {
|
|
||||||
SOURCE source = this.valueSerializer.handle(holder, data);
|
|
||||||
return holder.serialize(source);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.builder.list;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class ConfigListBuilder<V> {
|
|
||||||
|
|
||||||
protected final @NotNull ValueType<V> type;
|
|
||||||
|
|
||||||
public ConfigListBuilder(@NotNull ValueType<V> type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <S> @NotNull SourceListBuilder<S, V> from(@NotNull Class<S> sourceType) {
|
|
||||||
return from(ValueType.of(sourceType));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <S> @NotNull SourceListBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
|
||||||
return new SourceListBuilder<>(
|
|
||||||
ArrayList::new, sourceType, type,
|
|
||||||
ValueHandler.required(type),
|
|
||||||
ValueHandler.required(sourceType)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull SourceListBuilder<String, V> fromString() {
|
|
||||||
return new SourceListBuilder<>(
|
|
||||||
ArrayList::new, ValueType.STRING, type,
|
|
||||||
ValueHandler.required(type), ValueHandler.stringValue()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull SectionListBuilder<V> fromSection() {
|
|
||||||
return new SectionListBuilder<>(
|
|
||||||
ArrayList::new, type,
|
|
||||||
ValueHandler.required(type), ValueHandler.required()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cc.carm.lib.configuration.builder.list;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.collection.SimpleCollectionCreator;
|
||||||
|
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ConfigListCreator<V> extends SimpleCollectionCreator<V, List<V>, ConfiguredList<V>> {
|
||||||
|
|
||||||
|
public ConfigListCreator(@NotNull ValueType<V> type) {
|
||||||
|
super(type, ArrayList::new, ConfiguredList::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.builder.list;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class SectionListBuilder<V> extends AbstractSectionBuilder<List<V>, V, ConfiguredList<V>, SectionListBuilder<V>> {
|
|
||||||
|
|
||||||
protected @NotNull Supplier<? extends List<V>> constructor;
|
|
||||||
|
|
||||||
public SectionListBuilder(@NotNull Supplier<? extends List<V>> constructor,
|
|
||||||
@NotNull ValueType<V> paramType,
|
|
||||||
@NotNull ValueHandler<ConfigureSection, V> parser,
|
|
||||||
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
|
|
||||||
super(new ValueType<List<V>>() {
|
|
||||||
}, paramType, parser, serializer);
|
|
||||||
this.constructor = constructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public final @NotNull SectionListBuilder<V> defaults(@NotNull V... values) {
|
|
||||||
return defaults(new ArrayList<>(Arrays.asList(values)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final @NotNull SectionListBuilder<V> defaults(@NotNull Collection<V> values) {
|
|
||||||
return defaults(new ArrayList<>(values));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SectionListBuilder<V> constructor(@NotNull Supplier<? extends List<V>> constructor) {
|
|
||||||
this.constructor = constructor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <LIST extends List<V>> SectionListBuilder<V> construct(@NotNull LIST list) {
|
|
||||||
return constructor(() -> list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull SectionListBuilder<V> self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfiguredList<V> build() {
|
|
||||||
return new ConfiguredList<>(buildManifest(), constructor, buildAdapter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.builder.list;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class SourceListBuilder<SOURCE, V>
|
|
||||||
extends AbstractSourceBuilder<List<V>, SOURCE, V, ConfiguredList<V>, SourceListBuilder<SOURCE, V>> {
|
|
||||||
|
|
||||||
protected @NotNull Supplier<? extends List<V>> constructor;
|
|
||||||
|
|
||||||
public SourceListBuilder(@NotNull Supplier<? extends List<V>> constructor,
|
|
||||||
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<V> paramType,
|
|
||||||
@NotNull ValueHandler<SOURCE, V> parser, @NotNull ValueHandler<V, SOURCE> serializer) {
|
|
||||||
super(new ValueType<List<V>>() {
|
|
||||||
}, sourceType, paramType, parser, serializer);
|
|
||||||
this.constructor = constructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public final @NotNull SourceListBuilder<SOURCE, V> defaults(@NotNull V... values) {
|
|
||||||
return defaults(new ArrayList<>(Arrays.asList(values)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final @NotNull SourceListBuilder<SOURCE, V> defaults(@NotNull Collection<V> values) {
|
|
||||||
return defaults(new ArrayList<>(values));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull SourceListBuilder<SOURCE, V> self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfiguredList<V> build() {
|
|
||||||
return new ConfiguredList<>(buildManifest(), this.constructor, buildAdapter());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -32,9 +32,9 @@ public class ConfigMapBuilder<M extends Map<K, V>, K, V> {
|
|||||||
|
|
||||||
public @NotNull <S> SourceMapBuilder<M, S, K, V> from(@NotNull ValueType<S> sourceType) {
|
public @NotNull <S> SourceMapBuilder<M, S, K, V> from(@NotNull ValueType<S> sourceType) {
|
||||||
return from(
|
return from(
|
||||||
sourceType,
|
sourceType,
|
||||||
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
||||||
ValueHandler.required(valueType), ValueHandler.required()
|
ValueHandler.required(valueType), ValueHandler.required()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,35 +44,44 @@ public class ConfigMapBuilder<M extends Map<K, V>, K, V> {
|
|||||||
@NotNull ValueHandler<S, V> valueParser,
|
@NotNull ValueHandler<S, V> valueParser,
|
||||||
@NotNull ValueHandler<V, S> valueSerializer) {
|
@NotNull ValueHandler<V, S> valueSerializer) {
|
||||||
return new SourceMapBuilder<>(
|
return new SourceMapBuilder<>(
|
||||||
this.constructor, sourceType, keyType, valueType,
|
this.constructor, sourceType, keyType, valueType,
|
||||||
keyParser, keySerializer, valueParser, valueSerializer
|
keyParser, keySerializer, valueParser, valueSerializer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public @NotNull <S> SourceMapBuilder<M, Object, K, V> fromObject() {
|
||||||
|
return from(
|
||||||
|
ValueType.OBJECT,
|
||||||
|
ValueHandler.deserialize(keyType), ValueHandler.stringValue(),
|
||||||
|
ValueHandler.deserialize(valueType), ValueHandler.toObject()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SourceMapBuilder<M, String, K, V> fromString() {
|
public @NotNull SourceMapBuilder<M, String, K, V> fromString() {
|
||||||
return from(
|
return from(
|
||||||
ValueType.STRING,
|
ValueType.STRING,
|
||||||
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
||||||
ValueHandler.required(valueType), ValueHandler.stringValue()
|
ValueHandler.required(valueType), ValueHandler.stringValue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionMapBuilder<M, K, V> fromSection() {
|
public @NotNull SectionMapBuilder<M, K, V> fromSection() {
|
||||||
return fromSection(
|
return fromSection(
|
||||||
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
ValueHandler.required(keyType), ValueHandler.stringValue(),
|
||||||
ValueHandler.required(valueType), ValueHandler.required()
|
ValueHandler.required(valueType), ValueHandler.required()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionMapBuilder<M, K, V> fromSection(
|
public @NotNull SectionMapBuilder<M, K, V> fromSection(
|
||||||
@NotNull ValueHandler<String, K> keyParser,
|
@NotNull ValueHandler<String, K> keyParser,
|
||||||
@NotNull ValueHandler<K, String> keySerializer,
|
@NotNull ValueHandler<K, String> keySerializer,
|
||||||
@NotNull ValueHandler<ConfigureSection, V> valueParser,
|
@NotNull ValueHandler<ConfigureSection, V> valueParser,
|
||||||
@NotNull ValueHandler<V, Map<String, Object>> valueSerializer
|
@NotNull ValueHandler<V, Map<String, Object>> valueSerializer
|
||||||
) {
|
) {
|
||||||
return new SectionMapBuilder<>(
|
return new SectionMapBuilder<>(
|
||||||
this.constructor, keyType, valueType,
|
this.constructor, keyType, valueType,
|
||||||
keyParser, keySerializer, valueParser, valueSerializer
|
keyParser, keySerializer, valueParser, valueSerializer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ package cc.carm.lib.configuration.builder.map;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ConfigMapCreator<K, V> {
|
public class ConfigMapCreator<K, V> {
|
||||||
@@ -45,4 +42,8 @@ public class ConfigMapCreator<K, V> {
|
|||||||
return constructor(TreeMap::new);
|
return constructor(TreeMap::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigMapBuilder<TreeMap<K, V>, K, V> asTreeMap(@NotNull Comparator<? super K> comparator) {
|
||||||
|
return constructor(() -> new TreeMap<>(comparator));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,10 +14,7 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SectionMapBuilder<MAP extends Map<K, V>, K, V>
|
public class SectionMapBuilder<MAP extends Map<K, V>, K, V>
|
||||||
extends AbstractSectionBuilder<
|
extends AbstractSectionBuilder<Map<K, V>, V, ConfiguredMap<K, V>, SectionMapBuilder<MAP, K, V>> {
|
||||||
Map<K, V>, V, ConfiguredMap<K, V>,
|
|
||||||
SectionMapBuilder<MAP, K, V>
|
|
||||||
> {
|
|
||||||
|
|
||||||
protected final @NotNull ValueType<K> keyType;
|
protected final @NotNull ValueType<K> keyType;
|
||||||
|
|
||||||
@@ -75,16 +72,20 @@ public class SectionMapBuilder<MAP extends Map<K, V>, K, V>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull SectionMapBuilder<MAP, K, V> defaults(@NotNull K key, @NotNull V value) {
|
||||||
|
return defaults(map -> map.put(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
public @NotNull ValueAdapter<K> buildKeyAdapter() {
|
public @NotNull ValueAdapter<K> buildKeyAdapter() {
|
||||||
return new ValueAdapter<>(this.keyType)
|
return new ValueAdapter<>(this.keyType)
|
||||||
.parser((holder, type, data) -> {
|
.parser((holder, type, data) -> {
|
||||||
String source = holder.deserialize(String.class, data);
|
String source = holder.deserialize(String.class, data);
|
||||||
return this.keyParser.handle(holder, source);
|
return this.keyParser.handle(holder, source);
|
||||||
})
|
})
|
||||||
.serializer((holder, type, data) -> {
|
.serializer((holder, type, data) -> {
|
||||||
String source = this.keySerializer.handle(holder, data);
|
String source = this.keySerializer.handle(holder, data);
|
||||||
return holder.serialize(source);
|
return holder.serialize(source);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,10 +13,7 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
|
public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
|
||||||
extends AbstractSourceBuilder<
|
extends AbstractSourceBuilder<Map<K, V>, SOURCE, V, ConfiguredMap<K, V>, SourceMapBuilder<MAP, SOURCE, K, V>> {
|
||||||
Map<K, V>, SOURCE, V, ConfiguredMap<K, V>,
|
|
||||||
SourceMapBuilder<MAP, SOURCE, K, V>
|
|
||||||
> {
|
|
||||||
|
|
||||||
protected final @NotNull ValueType<K> keyType;
|
protected final @NotNull ValueType<K> keyType;
|
||||||
|
|
||||||
@@ -53,6 +50,10 @@ public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> defaults(@NotNull K key, @NotNull V value) {
|
||||||
|
return defaults(map -> map.put(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> parseKey(@NotNull DataFunction<String, K> keyParser) {
|
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> parseKey(@NotNull DataFunction<String, K> keyParser) {
|
||||||
return parseKey((holder, data) -> keyParser.handle(data));
|
return parseKey((holder, data) -> keyParser.handle(data));
|
||||||
}
|
}
|
||||||
@@ -73,14 +74,14 @@ public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
|
|||||||
|
|
||||||
public @NotNull ValueAdapter<K> buildKeyAdapter() {
|
public @NotNull ValueAdapter<K> buildKeyAdapter() {
|
||||||
return new ValueAdapter<>(this.keyType)
|
return new ValueAdapter<>(this.keyType)
|
||||||
.parser((holder, type, data) -> {
|
.parser((holder, type, data) -> {
|
||||||
String source = holder.deserialize(String.class, data);
|
String source = holder.deserialize(String.class, data);
|
||||||
return this.keyParser.handle(holder, source);
|
return this.keyParser.handle(holder, source);
|
||||||
})
|
})
|
||||||
.serializer((holder, type, data) -> {
|
.serializer((holder, type, data) -> {
|
||||||
String source = this.keySerializer.handle(holder, data);
|
String source = this.keySerializer.handle(holder, data);
|
||||||
return holder.serialize(source);
|
return holder.serialize(source);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.builder.value;
|
package cc.carm.lib.configuration.builder.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -39,8 +38,8 @@ public class ConfigValueBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection(
|
public @NotNull SectionValueBuilder<V> fromSection(
|
||||||
@NotNull ValueHandler<ConfigureSection, V> valueParser,
|
@NotNull ValueHandler<ConfigureSection, V> valueParser,
|
||||||
@NotNull ValueHandler<V, ? extends Map<String, Object>> valueSerializer
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> valueSerializer
|
||||||
) {
|
) {
|
||||||
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import cc.carm.lib.configuration.function.ValueHandler;
|
|||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class SourceValueBuilder<S, V> extends AbstractSourceBuilder<V, S, V, ConfiguredValue<V>, SourceValueBuilder<S, V>> {
|
public class SourceValueBuilder<S, V>
|
||||||
|
extends AbstractSourceBuilder<V, S, V, ConfiguredValue<V>, SourceValueBuilder<S, V>> {
|
||||||
|
|
||||||
|
|
||||||
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
|
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ConfigExceptionHandler {
|
||||||
|
|
||||||
|
void handle(@NotNull String path, @NotNull Throwable throwable);
|
||||||
|
|
||||||
|
static @NotNull ConfigExceptionHandler silence() {
|
||||||
|
return (path, throwable) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static @NotNull ConfigExceptionHandler print() {
|
||||||
|
return (path, throwable) -> {
|
||||||
|
System.err.println("Error occurred at path: " + path);
|
||||||
|
throwable.printStackTrace();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,8 +2,10 @@ package cc.carm.lib.configuration.function;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DataConsumer<T> {
|
public interface DataConsumer<T> extends Serializable {
|
||||||
|
|
||||||
void accept(@NotNull T data) throws Exception;
|
void accept(@NotNull T data) throws Exception;
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ package cc.carm.lib.configuration.function;
|
|||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DataFunction<T, R> {
|
public interface DataFunction<T, R> extends Serializable {
|
||||||
|
|
||||||
@NotNull R handle(@NotNull T data) throws Exception;
|
@NotNull R handle(@NotNull T data) throws Exception;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface DataValidator<T> extends Serializable {
|
||||||
|
|
||||||
|
void validate(@Nullable T value) throws Exception;
|
||||||
|
|
||||||
|
default DataValidator<T> compose(DataValidator<? super T> other) {
|
||||||
|
return value -> {
|
||||||
|
validate(value);
|
||||||
|
other.validate(value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ValueComposer<T, U> extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept the value and the data, and then compose the value.
|
||||||
|
*
|
||||||
|
* @param holder The configuration holder
|
||||||
|
* @param type The value type, e.g. {@link java.util.List}, {@link java.util.Map}, etc.
|
||||||
|
* @param data The unit data
|
||||||
|
* @throws Exception If an error occurs
|
||||||
|
*/
|
||||||
|
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull T type, @NotNull U data) throws Exception;
|
||||||
|
|
||||||
|
default ValueComposer<T, U> andThen(ValueComposer<? super T, ? super U> after) {
|
||||||
|
return (holder, unit, data) -> {
|
||||||
|
accept(holder, unit, data);
|
||||||
|
after.accept(holder, unit, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.function;
|
|
||||||
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface ValueConsumer<U, T> {
|
|
||||||
|
|
||||||
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull U unit, @NotNull T data) throws Exception;
|
|
||||||
|
|
||||||
default ValueConsumer<U, T> andThen(ValueConsumer<? super U, ? super T> after) {
|
|
||||||
return (holder, unit, data) -> {
|
|
||||||
accept(holder, unit, data);
|
|
||||||
after.accept(holder, unit, data);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -7,10 +7,11 @@ import org.jetbrains.annotations.Contract;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ValueHandler<T, R> {
|
public interface ValueHandler<T, R> extends Serializable {
|
||||||
|
|
||||||
@Nullable R handle(@NotNull ConfigurationHolder<?> holder, @NotNull T data) throws Exception;
|
@Nullable R handle(@NotNull ConfigurationHolder<?> holder, @NotNull T data) throws Exception;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ValueValidator<T> extends Serializable {
|
||||||
|
|
||||||
|
void validate(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception;
|
||||||
|
|
||||||
|
default ValueValidator<T> and(ValueValidator<? super T> other) {
|
||||||
|
return (holder, value) -> {
|
||||||
|
validate(holder, value);
|
||||||
|
other.validate(holder, value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static <V> ValueValidator<V> none() {
|
||||||
|
return (holder, data) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static <V> ValueValidator<V> nonnull() {
|
||||||
|
return nonnull("Value cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
static <V> ValueValidator<V> nonnull(String message) {
|
||||||
|
return (holder, data) -> {
|
||||||
|
if (data == null) throw new IllegalArgumentException(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static <V extends Number> ValueValidator<V> range(V min, V max) {
|
||||||
|
return range(min, max, "Value must be in range [" + min + ", " + max + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static <V extends Number> ValueValidator<V> range(V min, V max, String message) {
|
||||||
|
return (holder, data) -> {
|
||||||
|
if (data.doubleValue() < min.doubleValue() || data.doubleValue() > max.doubleValue()) {
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,9 @@ package cc.carm.lib.configuration.source;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.*;
|
import cc.carm.lib.configuration.adapter.*;
|
||||||
import cc.carm.lib.configuration.adapter.strandard.StandardAdapters;
|
import cc.carm.lib.configuration.adapter.strandard.StandardAdapters;
|
||||||
|
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
|
import cc.carm.lib.configuration.function.ValueValidator;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
@@ -28,20 +30,22 @@ import java.util.function.Supplier;
|
|||||||
* @param <SELF> Self builder, for further implement support.
|
* @param <SELF> Self builder, for further implement support.
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigurationFactory<
|
public abstract class ConfigurationFactory<
|
||||||
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
||||||
HOLDER extends ConfigurationHolder<SOURCE>,
|
HOLDER extends ConfigurationHolder<SOURCE>,
|
||||||
SELF
|
SELF
|
||||||
> {
|
> {
|
||||||
|
|
||||||
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
protected @NotNull ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
||||||
protected ConfigurationOptionHolder options = new ConfigurationOptionHolder();
|
protected @NotNull ConfigurationOptionHolder options = new ConfigurationOptionHolder();
|
||||||
protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>();
|
protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>();
|
||||||
protected ConfigurationInitializer initializer = new ConfigurationInitializer();
|
protected @NotNull ConfigurationInitializer initializer = new ConfigurationInitializer();
|
||||||
|
protected @NotNull ConfigExceptionHandler exceptionHandler = ConfigExceptionHandler.print();
|
||||||
|
|
||||||
public ConfigurationFactory() {
|
protected ConfigurationFactory() {
|
||||||
this.adapters.register(StandardAdapters.PRIMITIVES);
|
this.adapters.register(StandardAdapters.PRIMITIVES);
|
||||||
this.adapters.register(StandardAdapters.SECTIONS);
|
this.adapters.register(StandardAdapters.SECTIONS);
|
||||||
this.adapters.register(StandardAdapters.ENUMS);
|
this.adapters.register(StandardAdapters.ENUMS);
|
||||||
|
this.adapters.register(StandardAdapters.UUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract SELF self();
|
protected abstract SELF self();
|
||||||
@@ -146,6 +150,11 @@ public abstract class ConfigurationFactory<
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SELF exceptionally(@NotNull ConfigExceptionHandler handler) {
|
||||||
|
this.exceptionHandler = handler;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supply the base path generator for this configuration holder
|
* Supply the base path generator for this configuration holder
|
||||||
*
|
*
|
||||||
@@ -153,9 +162,7 @@ public abstract class ConfigurationFactory<
|
|||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public SELF pathGenerator(PathGenerator generator) {
|
public SELF pathGenerator(PathGenerator generator) {
|
||||||
return initializer(loader -> {
|
return initializer(loader -> loader.pathGenerator(generator));
|
||||||
loader.pathGenerator(generator);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,6 +181,19 @@ public abstract class ConfigurationFactory<
|
|||||||
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
|
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new annotation for {@link ValueValidator} to the configuration loader
|
||||||
|
*
|
||||||
|
* @param annotation The {@link Annotation}
|
||||||
|
* @param builder The {@link Function} to build the {@link ValueValidator} from the annotation
|
||||||
|
* @param <A> The annotation type
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public <A extends Annotation> SELF validAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull Function<A, ValueValidator<Object>> builder) {
|
||||||
|
return initializer(loader -> loader.registerValidAnnotation(annotation, builder));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the configuration holder.
|
* Build the configuration holder.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ package cc.carm.lib.configuration.source;
|
|||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
|
import cc.carm.lib.configuration.source.meta.StandardMeta;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import org.jetbrains.annotations.Contract;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.UnmodifiableView;
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
@@ -18,6 +20,8 @@ import org.jetbrains.annotations.UnmodifiableView;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, SOURCE>> {
|
public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, SOURCE>> {
|
||||||
|
|
||||||
@@ -27,14 +31,25 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
|
|
||||||
protected final @NotNull ConfigurationInitializer initializer;
|
protected final @NotNull ConfigurationInitializer initializer;
|
||||||
|
|
||||||
|
protected @NotNull ConfigExceptionHandler exceptionHandler;
|
||||||
|
|
||||||
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
|
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
|
||||||
@NotNull ConfigurationOptionHolder options,
|
@NotNull ConfigurationOptionHolder options,
|
||||||
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
||||||
@NotNull ConfigurationInitializer initializer) {
|
@NotNull ConfigurationInitializer initializer) {
|
||||||
|
this(adapters, options, metadata, initializer, ConfigExceptionHandler.print());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
|
||||||
|
@NotNull ConfigurationOptionHolder options,
|
||||||
|
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
||||||
|
@NotNull ConfigurationInitializer initializer,
|
||||||
|
@NotNull ConfigExceptionHandler exceptionHandler) {
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
this.adapters = adapters;
|
this.adapters = adapters;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
|
this.exceptionHandler = exceptionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract @NotNull SOURCE config();
|
public abstract @NotNull SOURCE config();
|
||||||
@@ -51,7 +66,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <O> O option(@NotNull ConfigurationOption<O> option) {
|
public <O> @NotNull O option(@NotNull ConfigurationOption<O> option) {
|
||||||
return options().get(option);
|
return options().get(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +81,26 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
@NotNull
|
@NotNull
|
||||||
@UnmodifiableView
|
@UnmodifiableView
|
||||||
public <M> Map<String, M> extractMetadata(@NotNull ConfigurationMetadata<M> type) {
|
public <M> Map<String, M> extractMetadata(@NotNull ConfigurationMetadata<M> type) {
|
||||||
|
return extractMetadata(type, Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@UnmodifiableView
|
||||||
|
public <M> Map<String, M> extractMetadata(@NotNull ConfigurationMetadata<M> type, @NotNull Predicate<@Nullable M> filter) {
|
||||||
Map<String, M> metas = new LinkedHashMap<>();
|
Map<String, M> metas = new LinkedHashMap<>();
|
||||||
for (Map.Entry<String, ConfigurationMetaHolder> entry : this.metadata.entrySet()) {
|
for (Map.Entry<String, ConfigurationMetaHolder> entry : this.metadata.entrySet()) {
|
||||||
M data = entry.getValue().get(type);
|
M data = entry.getValue().get(type);
|
||||||
if (data != null) metas.put(entry.getKey(), data);
|
if (filter.test(data)) metas.put(entry.getKey(), data);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableMap(metas);
|
return Collections.unmodifiableMap(metas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@UnmodifiableView
|
||||||
|
public Map<String, ConfigValue<?, ?>> registeredValues() {
|
||||||
|
return extractMetadata(StandardMeta.VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
public ValueAdapterRegistry adapters() {
|
public ValueAdapterRegistry adapters() {
|
||||||
return this.adapters;
|
return this.adapters;
|
||||||
}
|
}
|
||||||
@@ -82,17 +109,17 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
return initializer;
|
return initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,null -> null")
|
@Nullable
|
||||||
public <T> T deserialize(@NotNull Class<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull Class<T> type, @Nullable Object source) throws Exception {
|
||||||
return adapters().deserialize(this, type, source);
|
return adapters().deserialize(this, type, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,null -> null")
|
@Nullable
|
||||||
public <T> T deserialize(@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
||||||
return adapters().deserialize(this, type, source);
|
return adapters().deserialize(this, type, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("null -> null")
|
@Nullable
|
||||||
public <T> Object serialize(@Nullable T value) throws Exception {
|
public <T> Object serialize(@Nullable T value) throws Exception {
|
||||||
return adapters().serialize(this, value);
|
return adapters().serialize(this, value);
|
||||||
}
|
}
|
||||||
@@ -101,7 +128,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
try {
|
try {
|
||||||
initializer.initialize(this, configClass);
|
initializer.initialize(this, configClass);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throwing(configClass.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,12 +136,20 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
|||||||
try {
|
try {
|
||||||
initializer.initialize(this, config);
|
initializer.initialize(this, config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throwing(config.getClass().getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(@NotNull ValueManifest<?> value) {
|
public void initialize(@NotNull ValueManifest<?, ?> value) {
|
||||||
value.holder(this);
|
value.holder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void throwing(@NotNull String path, @NotNull Throwable e) {
|
||||||
|
this.exceptionHandler.handle(path, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exceptionally(@NotNull ConfigExceptionHandler handler) {
|
||||||
|
this.exceptionHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -5,26 +5,27 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ConfigInitializeHandler<T> {
|
public interface ConfigInitializeHandler<T, V> {
|
||||||
|
|
||||||
static <T> ConfigInitializeHandler<T> start() {
|
static <T, V> ConfigInitializeHandler<T, V> start() {
|
||||||
return (provider, path, value) -> {
|
return (provider, path, value, instance) -> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void whenInitialize(@NotNull ConfigurationHolder<?> holder, @Nullable String path, @NotNull T value) throws Exception;
|
void whenInitialize(@NotNull ConfigurationHolder<?> holder, @Nullable String path,
|
||||||
|
@NotNull T value, @Nullable V instance) throws Exception;
|
||||||
|
|
||||||
default ConfigInitializeHandler<T> andThen(ConfigInitializeHandler<T> after) {
|
default ConfigInitializeHandler<T, V> andThen(ConfigInitializeHandler<T, V> after) {
|
||||||
return (provider, path, value) -> {
|
return (provider, path, value, instance) -> {
|
||||||
whenInitialize(provider, path, value);
|
whenInitialize(provider, path, value, instance);
|
||||||
after.whenInitialize(provider, path, value);
|
after.whenInitialize(provider, path, value, instance);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
default ConfigInitializeHandler<T> compose(ConfigInitializeHandler<T> before) {
|
default ConfigInitializeHandler<T, V> compose(ConfigInitializeHandler<T, V> before) {
|
||||||
return (provider, path, value) -> {
|
return (provider, path, value, instance) -> {
|
||||||
before.whenInitialize(provider, path, value);
|
before.whenInitialize(provider, path, value, instance);
|
||||||
whenInitialize(provider, path, value);
|
whenInitialize(provider, path, value, instance);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-28
@@ -1,6 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.source.loader;
|
package cc.carm.lib.configuration.source.loader;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
|
import cc.carm.lib.configuration.function.ValueValidator;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
import cc.carm.lib.configuration.source.meta.StandardMeta;
|
import cc.carm.lib.configuration.source.meta.StandardMeta;
|
||||||
@@ -21,18 +22,18 @@ import java.util.function.Function;
|
|||||||
public class ConfigurationInitializer {
|
public class ConfigurationInitializer {
|
||||||
|
|
||||||
protected @NotNull PathGenerator pathGenerator;
|
protected @NotNull PathGenerator pathGenerator;
|
||||||
protected @NotNull ConfigInitializeHandler<Field> fieldInitializer;
|
protected @NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer;
|
||||||
protected @NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer;
|
protected @NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer;
|
||||||
|
|
||||||
public ConfigurationInitializer() {
|
public ConfigurationInitializer() {
|
||||||
this(PathGenerator.of(), ConfigInitializeHandler.start(), ConfigInitializeHandler.start());
|
this(PathGenerator.of(), ConfigInitializeHandler.start(), ConfigInitializeHandler.start());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationInitializer(@NotNull PathGenerator pathGenerator,
|
public ConfigurationInitializer(@NotNull PathGenerator pathGenerator,
|
||||||
@NotNull ConfigInitializeHandler<Field> fieldInitializer,
|
@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer,
|
||||||
@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
|
||||||
this.pathGenerator = pathGenerator;
|
this.pathGenerator = pathGenerator;
|
||||||
this.fieldInitializer = fieldInitializer;
|
this.valueInitializer = valueInitializer;
|
||||||
this.classInitializer = classInitializer;
|
this.classInitializer = classInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,34 +45,34 @@ public class ConfigurationInitializer {
|
|||||||
return pathGenerator;
|
return pathGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigInitializeHandler<Field> fieldInitializer() {
|
public ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer() {
|
||||||
return fieldInitializer;
|
return valueInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field> fieldInitializer) {
|
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
|
||||||
this.fieldInitializer = fieldInitializer;
|
this.valueInitializer = fieldInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigInitializeHandler<Class<? extends Configuration>> classInitializer() {
|
public ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer() {
|
||||||
return classInitializer;
|
return classInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void classInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
public void classInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
|
||||||
this.classInitializer = classInitializer;
|
this.classInitializer = classInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field> fieldInitializer) {
|
public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
|
||||||
this.fieldInitializer = this.fieldInitializer.andThen(fieldInitializer);
|
this.valueInitializer = this.valueInitializer.andThen(fieldInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendClassInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
public void appendClassInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
|
||||||
this.classInitializer = this.classInitializer.andThen(classInitializer);
|
this.classInitializer = this.classInitializer.andThen(classInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T, A extends Annotation> void registerClassAnnotation(@NotNull Class<A> annotation,
|
public <T, A extends Annotation> void registerClassAnnotation(@NotNull Class<A> annotation,
|
||||||
@NotNull ConfigurationMetadata<T> metadata,
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
@NotNull Function<A, T> extractor) {
|
@NotNull Function<A, T> extractor) {
|
||||||
appendClassInitializer((holder, path, clazz) -> {
|
appendClassInitializer((holder, path, clazz, instance) -> {
|
||||||
A data = clazz.getAnnotation(annotation);
|
A data = clazz.getAnnotation(annotation);
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
@@ -81,7 +82,7 @@ public class ConfigurationInitializer {
|
|||||||
public <T, A extends Annotation> void registerFieldAnnotation(@NotNull Class<A> annotation,
|
public <T, A extends Annotation> void registerFieldAnnotation(@NotNull Class<A> annotation,
|
||||||
@NotNull ConfigurationMetadata<T> metadata,
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
@NotNull Function<A, T> extractor) {
|
@NotNull Function<A, T> extractor) {
|
||||||
appendFieldInitializer((holder, path, field) -> {
|
appendFieldInitializer((holder, path, field, instance) -> {
|
||||||
A data = field.getAnnotation(annotation);
|
A data = field.getAnnotation(annotation);
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
@@ -95,6 +96,14 @@ public class ConfigurationInitializer {
|
|||||||
registerFieldAnnotation(annotation, metadata, extractor);
|
registerFieldAnnotation(annotation, metadata, extractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <A extends Annotation> void registerValidAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull Function<A, ValueValidator<Object>> builder) {
|
||||||
|
appendFieldInitializer((holder, path, field, instance) -> {
|
||||||
|
A data = field.getAnnotation(annotation);
|
||||||
|
if (data == null) return;
|
||||||
|
instance.validate((h, t) -> builder.apply(data).validate(h, t));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
||||||
return pathGenerator.getFieldPath(holder, parentPath, field);
|
return pathGenerator.getFieldPath(holder, parentPath, field);
|
||||||
@@ -123,9 +132,9 @@ public class ConfigurationInitializer {
|
|||||||
@Nullable String parentPath, @Nullable Field configField) {
|
@Nullable String parentPath, @Nullable Field configField) {
|
||||||
String path = getClassPath(holder, parentPath, root.getClass(), configField);
|
String path = getClassPath(holder, parentPath, root.getClass(), configField);
|
||||||
try {
|
try {
|
||||||
this.classInitializer.whenInitialize(holder, path, root.getClass());
|
this.classInitializer.whenInitialize(holder, path, root.getClass(), root);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
holder.throwing(path, e);
|
||||||
}
|
}
|
||||||
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path));
|
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path));
|
||||||
}
|
}
|
||||||
@@ -140,9 +149,9 @@ public class ConfigurationInitializer {
|
|||||||
String path = getClassPath(holder, parentPath, clazz, configField);
|
String path = getClassPath(holder, parentPath, clazz, configField);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz);
|
this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz, configField);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
holder.throwing(path, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
@@ -163,21 +172,21 @@ public class ConfigurationInitializer {
|
|||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
Object object = field.get(source);
|
Object object = field.get(source);
|
||||||
//
|
//
|
||||||
if (object instanceof ConfigValue<?>) {
|
if (object instanceof ConfigValue<?, ?>) {
|
||||||
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
||||||
ConfigValue<?> value = (ConfigValue<?>) object;
|
ConfigValue<?, ?> value = (ConfigValue<?, ?>) object;
|
||||||
String path = getFieldPath(holder, parent, field);
|
String path = getFieldPath(holder, parent, field);
|
||||||
if (path == null) return;
|
if (path == null) return;
|
||||||
value.initialize(holder, path);
|
value.initialize(holder, path);
|
||||||
holder.metadata(path).set(StandardMeta.UNIT, true); // Mark the minimal config value unit.
|
holder.metadata(path).set(StandardMeta.VALUE, value); // Mark the minimal config value unit.
|
||||||
try {
|
|
||||||
this.fieldInitializer.whenInitialize(holder, path, field);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (holder.option(StandardOptions.SET_DEFAULTS)) {
|
if (holder.option(StandardOptions.SET_DEFAULTS)) {
|
||||||
value.setDefault(); // Set default value.
|
value.setDefault(); // Set default value.
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
this.valueInitializer.whenInitialize(holder, path, field, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
holder.throwing(path, e);
|
||||||
|
}
|
||||||
if (holder.option(StandardOptions.PRELOAD)) {
|
if (holder.option(StandardOptions.PRELOAD)) {
|
||||||
value.get(); // Preload the value by calling #get method.
|
value.get(); // Preload the value by calling #get method.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,21 +100,21 @@ public class PathGenerator {
|
|||||||
*/
|
*/
|
||||||
public static String covertPathName(String name) {
|
public static String covertPathName(String name) {
|
||||||
return name
|
return name
|
||||||
// Replace all uppercase letters with dashes
|
// Replace all uppercase letters with dashes
|
||||||
.replaceAll("[A-Z]", "=$0")
|
.replaceAll("[A-Z]", "=$0")
|
||||||
// If the first letter is also capitalized,
|
// If the first letter is also capitalized,
|
||||||
// it will also be converted and the first dash will need to be removed
|
// it will also be converted and the first dash will need to be removed
|
||||||
.replaceAll("^=(.*)$", "$1")
|
.replaceAll("^=(.*)$", "$1")
|
||||||
// Because the name may contain _, it needs to be treated a little differently
|
// Because the name may contain _, it needs to be treated a little differently
|
||||||
.replaceAll("_=([A-Z])", "_$1")
|
.replaceAll("_=([A-Z])", "_$1")
|
||||||
// The content that is not named in all caps is then converted
|
// The content that is not named in all caps is then converted
|
||||||
.replaceAll("([a-z])=([A-Z])", "$1_$2")
|
.replaceAll("([a-z])=([A-Z])", "$1_$2")
|
||||||
// Remove any extra horizontal lines
|
// Remove any extra horizontal lines
|
||||||
.replace("=", "")
|
.replace("=", "")
|
||||||
// Replace the underscore with a dash
|
// Replace the underscore with a dash
|
||||||
.replace("_", "-")
|
.replace("_", "-")
|
||||||
// Finally, convert it to all lowercase
|
// Finally, convert it to all lowercase
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package cc.carm.lib.configuration.source.meta;
|
package cc.carm.lib.configuration.source.meta;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
|
|
||||||
public interface StandardMeta {
|
public interface StandardMeta {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To mark the {@link cc.carm.lib.configuration.value.ConfigValue} as a minimal unit path.
|
* To mark the {@link ConfigValue} instance of specific path.
|
||||||
*/
|
*/
|
||||||
ConfigurationMetadata<Boolean> UNIT = ConfigurationMetadata.of(false);
|
ConfigurationMetadata<ConfigValue<?, ?>> VALUE = ConfigurationMetadata.of();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ public interface StandardOptions {
|
|||||||
ConfigurationOption<Boolean> LOAD_SUB_CLASSES = of(true);
|
ConfigurationOption<Boolean> LOAD_SUB_CLASSES = of(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to pre parse the config values.
|
* Whether to pre parse the config values,
|
||||||
* <br> if false, the values will be parsed when calling
|
* may good to set true if you want to keep the config format.
|
||||||
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
|
|
||||||
* <br> if true, the values will be parsed when
|
* <br> if true, the values will be parsed when
|
||||||
* {@link ConfigurationHolder#initialize(Configuration)}.
|
* {@link ConfigurationHolder#initialize(Configuration)}.
|
||||||
|
* <br> if false, the values will be parsed when calling
|
||||||
|
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
|
||||||
*/
|
*/
|
||||||
ConfigurationOption<Boolean> PRELOAD = of(false);
|
ConfigurationOption<Boolean> PRELOAD = of(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ public interface ConfigureSection {
|
|||||||
return (parent().isRoot() ? "" : parent().fullPath() + pathSeparator()) + path();
|
return (parent().isRoot() ? "" : parent().fullPath() + pathSeparator()) + path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path separator for the section.
|
* Get the path separator for the section.
|
||||||
*
|
*
|
||||||
@@ -143,6 +142,17 @@ public interface ConfigureSection {
|
|||||||
return getValues(false);
|
return getValues(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get this section as a map.
|
||||||
|
* <p>
|
||||||
|
* In this map, child {@link ConfigureSection}s will also be represented as {@link Map}s.
|
||||||
|
*
|
||||||
|
* @return Map of data values contained within this Section.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
@UnmodifiableView
|
||||||
|
Map<String, Object> asMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a stream of all values in this section.
|
* Create a stream of all values in this section.
|
||||||
*
|
*
|
||||||
@@ -153,7 +163,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all keys in this section.
|
* Iterates over all key-values in this section (include child sections)
|
||||||
*
|
*
|
||||||
* @param action The action to apply to each key.
|
* @param action The action to apply to each key.
|
||||||
*/
|
*/
|
||||||
@@ -467,7 +477,7 @@ public interface ConfigureSection {
|
|||||||
* @return The boolean if the path exists and is a boolean, otherwise false.
|
* @return The boolean if the path exists and is a boolean, otherwise false.
|
||||||
*/
|
*/
|
||||||
default boolean getBoolean(@NotNull String path) {
|
default boolean getBoolean(@NotNull String path) {
|
||||||
return getBoolean(path, false);
|
return getBoolean(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -499,7 +509,7 @@ public interface ConfigureSection {
|
|||||||
* @return The byte if the path exists and is a byte, otherwise 0.
|
* @return The byte if the path exists and is a byte, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Byte getByte(@NotNull String path) {
|
default @Nullable Byte getByte(@NotNull String path) {
|
||||||
return getByte(path, (byte) 0);
|
return getByte(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -531,7 +541,7 @@ public interface ConfigureSection {
|
|||||||
* @return The short if the path exists and is a short, otherwise 0.
|
* @return The short if the path exists and is a short, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Short getShort(@NotNull String path) {
|
default @Nullable Short getShort(@NotNull String path) {
|
||||||
return getShort(path, (short) 0);
|
return getShort(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -563,7 +573,7 @@ public interface ConfigureSection {
|
|||||||
* @return The int if the path exists and is an int, otherwise 0.
|
* @return The int if the path exists and is an int, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Integer getInt(@NotNull String path) {
|
default @Nullable Integer getInt(@NotNull String path) {
|
||||||
return getInt(path, 0);
|
return getInt(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -596,7 +606,7 @@ public interface ConfigureSection {
|
|||||||
* @return The long if the path exists and is a long, otherwise 0.
|
* @return The long if the path exists and is a long, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Long getLong(@NotNull String path) {
|
default @Nullable Long getLong(@NotNull String path) {
|
||||||
return getLong(path, 0L);
|
return getLong(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -628,7 +638,7 @@ public interface ConfigureSection {
|
|||||||
* @return The float if the path exists and is a float, otherwise 0.
|
* @return The float if the path exists and is a float, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Float getFloat(@NotNull String path) {
|
default @Nullable Float getFloat(@NotNull String path) {
|
||||||
return getFloat(path, 0.0F);
|
return getFloat(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -660,7 +670,7 @@ public interface ConfigureSection {
|
|||||||
* @return The double if the path exists and is a double, otherwise 0.
|
* @return The double if the path exists and is a double, otherwise 0.
|
||||||
*/
|
*/
|
||||||
default @Nullable Double getDouble(@NotNull String path) {
|
default @Nullable Double getDouble(@NotNull String path) {
|
||||||
return getDouble(path, 0.0D);
|
return getDouble(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -682,7 +692,7 @@ public interface ConfigureSection {
|
|||||||
* @return True if the value is present and is a char, false otherwise.
|
* @return True if the value is present and is a char, false otherwise.
|
||||||
*/
|
*/
|
||||||
default boolean isChar(@NotNull String path) {
|
default boolean isChar(@NotNull String path) {
|
||||||
return isType(path, Boolean.class);
|
return isType(path, Character.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -740,7 +750,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of values from the section
|
* Get a list of values from current section
|
||||||
* <p>
|
* <p>
|
||||||
* If the path does not exist, an empty list will be returned
|
* If the path does not exist, an empty list will be returned
|
||||||
* <br>Any changes please use {@link #set(String, Object)} after changes
|
* <br>Any changes please use {@link #set(String, Object)} after changes
|
||||||
@@ -755,7 +765,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of strings from the section
|
* Get a list of strings from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -766,7 +776,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of integer from the section
|
* Get a list of integer from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -777,7 +787,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of long from the section
|
* Get a list of long from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -788,7 +798,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of double from the section
|
* Get a list of double from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -799,7 +809,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of floats from the section
|
* Get a list of floats from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -810,7 +820,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of bytes from the section
|
* Get a list of bytes from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -821,7 +831,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of char from the section
|
* Get a list of char from current section
|
||||||
* <p> Limitations see {@link #getList(String, DataFunction)}
|
* <p> Limitations see {@link #getList(String, DataFunction)}
|
||||||
*
|
*
|
||||||
* @param path The path to get the list from
|
* @param path The path to get the list from
|
||||||
@@ -832,7 +842,24 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the specific type of collection from the section.
|
* Get a list of {@link ConfigureSection} from current section
|
||||||
|
*
|
||||||
|
* @param path The path to get the list from
|
||||||
|
* @return The list of {@link ConfigureSection}
|
||||||
|
*/
|
||||||
|
default @NotNull List<ConfigureSection> getSectionList(@NotNull String path) {
|
||||||
|
return getList(path, obj -> {
|
||||||
|
if (obj instanceof ConfigureSection) {
|
||||||
|
return (ConfigureSection) obj;
|
||||||
|
} else if (obj instanceof Map) {
|
||||||
|
return createSection(childPath(path), (Map<?, ?>) obj);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the specific type of collection from current section.
|
||||||
*
|
*
|
||||||
* @param path The path to get the collection from
|
* @param path The path to get the collection from
|
||||||
* @param constructor The constructor of the collection
|
* @param constructor The constructor of the collection
|
||||||
@@ -848,7 +875,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the specific type of steam from the section.
|
* Get the specific type of steam from current section.
|
||||||
*
|
*
|
||||||
* @param path The path to get the stream from
|
* @param path The path to get the stream from
|
||||||
* @return The stream of values
|
* @return The stream of values
|
||||||
@@ -859,7 +886,7 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the specific type of steam from the section.
|
* Get the specific type of steam from current section.
|
||||||
*
|
*
|
||||||
* @param path The path to get the stream from
|
* @param path The path to get the stream from
|
||||||
* @param parser The function to parse the values
|
* @param parser The function to parse the values
|
||||||
@@ -876,9 +903,9 @@ public interface ConfigureSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static <T, C extends Collection<T>> @NotNull C parseCollection(
|
static <T, C extends Collection<T>> @NotNull C parseCollection(
|
||||||
@Nullable List<?> data,
|
@Nullable List<?> data,
|
||||||
@NotNull Supplier<C> constructor,
|
@NotNull Supplier<C> constructor,
|
||||||
@NotNull DataFunction<Object, T> parser
|
@NotNull DataFunction<Object, T> parser
|
||||||
) {
|
) {
|
||||||
C values = constructor.get();
|
C values = constructor.get();
|
||||||
if (data == null) return values;
|
if (data == null) return values;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import java.util.Set;
|
|||||||
* @see ConfigureSection
|
* @see ConfigureSection
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigureSource<
|
public abstract class ConfigureSource<
|
||||||
SECTION extends ConfigureSection, ORIGINAL,
|
SECTION extends ConfigureSection, ORIGINAL,
|
||||||
SELF extends ConfigureSource<SECTION, ORIGINAL, SELF>>
|
SELF extends ConfigureSource<SECTION, ORIGINAL, SELF>>
|
||||||
implements ConfigureSection {
|
implements ConfigureSection {
|
||||||
|
|
||||||
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
|
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
|
||||||
protected long lastUpdateMillis;
|
protected long lastUpdateMillis;
|
||||||
@@ -107,6 +107,11 @@ public abstract class ConfigureSource<
|
|||||||
return section().getKeys(deep);
|
return section().getKeys(deep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull @UnmodifiableView Map<String, Object> asMap() {
|
||||||
|
return section().asMap();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ConfigureSection createSection(@NotNull String path, @NotNull Map<?, ?> data) {
|
public @NotNull ConfigureSection createSection(@NotNull String path, @NotNull Map<?, ?> data) {
|
||||||
return section().createSection(path, data);
|
return section().createSection(path, data);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.value;
|
package cc.carm.lib.configuration.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -33,9 +34,9 @@ import java.util.Optional;
|
|||||||
* @see ValueManifest Base class providing metadata and default value handling
|
* @see ValueManifest Base class providing metadata and default value handling
|
||||||
* @see ConfigurationHolder Responsible for configuration source persistence
|
* @see ConfigurationHolder Responsible for configuration source persistence
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
public abstract class ConfigValue<T, U> extends ValueManifest<T, U> {
|
||||||
|
|
||||||
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
protected ConfigValue(@NotNull ValueManifest<T, U> manifest) {
|
||||||
super(manifest);
|
super(manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +55,18 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
* @return Configured value or default value
|
* @return Configured value or default value
|
||||||
*/
|
*/
|
||||||
public T getOrDefault() {
|
public T getOrDefault() {
|
||||||
return optional().orElse(defaults());
|
return getOr(defaults());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the configured value, or returns the specified default value if not present.
|
||||||
|
*
|
||||||
|
* @param defaults The default value to return if the configured value is not present
|
||||||
|
* @return Configured value or specified default value
|
||||||
|
*/
|
||||||
|
@Contract("!null -> !null")
|
||||||
|
public T getOr(T defaults) {
|
||||||
|
return optional().orElse(defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,47 +1,59 @@
|
|||||||
package cc.carm.lib.configuration.value;
|
package cc.carm.lib.configuration.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.function.ValueValidator;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ValueManifest<T> {
|
public class ValueManifest<TYPE, UNIT> {
|
||||||
|
|
||||||
protected final @NotNull ValueType<T> type;
|
protected final @NotNull ValueType<TYPE> type;
|
||||||
protected final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer;
|
protected final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer;
|
||||||
|
|
||||||
protected @Nullable ConfigurationHolder<?> holder;
|
protected @Nullable ConfigurationHolder<?> holder;
|
||||||
protected @Nullable String path; // Section path
|
protected @Nullable String path; // Section path
|
||||||
|
|
||||||
protected @NotNull Supplier<@Nullable T> defaultSupplier;
|
protected @NotNull ValueValidator<UNIT> validator;
|
||||||
|
protected @NotNull Supplier<@Nullable TYPE> defaultSupplier;
|
||||||
|
|
||||||
|
public ValueManifest(@NotNull ValueType<TYPE> type) {
|
||||||
public ValueManifest(@NotNull ValueType<T> type) {
|
this(type, () -> null, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
|
||||||
this(type, () -> null, EMPTY_INITIALIZER, null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull T defaultValue) {
|
public ValueManifest(@NotNull TYPE defaultValue) {
|
||||||
this(ValueType.of(defaultValue), () -> defaultValue);
|
this(ValueType.of(defaultValue), () -> defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier) {
|
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier) {
|
||||||
this(type, defaultSupplier, EMPTY_INITIALIZER, null, null);
|
this(type, defaultSupplier, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
public ValueManifest(@NotNull ValueType<TYPE> type,
|
||||||
|
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||||
|
@NotNull ValueValidator<UNIT> validator) {
|
||||||
|
this(type, defaultSupplier, validator, EMPTY_INITIALIZER, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||||
|
@NotNull ValueValidator<UNIT> validator,
|
||||||
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
|
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
|
||||||
this(type, defaultSupplier, initializer, null, null);
|
this(type, defaultSupplier, validator, initializer, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
public ValueManifest(@NotNull ValueType<TYPE> type,
|
||||||
|
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||||
|
@NotNull ValueValidator<UNIT> validator,
|
||||||
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
|
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
|
||||||
@Nullable ConfigurationHolder<?> holder, @Nullable String path) {
|
@Nullable ConfigurationHolder<?> holder, @Nullable String path) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.validator = validator;
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
this.defaultSupplier = defaultSupplier;
|
this.defaultSupplier = defaultSupplier;
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
@@ -49,8 +61,8 @@ public class ValueManifest<T> {
|
|||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueManifest(@NotNull ValueManifest<T> manifest) {
|
protected ValueManifest(@NotNull ValueManifest<TYPE, UNIT> manifest) {
|
||||||
this(manifest.type, manifest.defaultSupplier, manifest.initializer, manifest.holder, manifest.path);
|
this(manifest.type, manifest.defaultSupplier, manifest.validator, manifest.initializer, manifest.holder, manifest.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
|
public void initialize(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
|
||||||
@@ -63,7 +75,7 @@ public class ValueManifest<T> {
|
|||||||
if (holder != null && path != null) this.initializer.accept(holder, path);
|
if (holder != null && path != null) this.initializer.accept(holder, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ValueType<T> type() {
|
public @NotNull ValueType<TYPE> type() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,50 +87,77 @@ public class ValueManifest<T> {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable T defaults() {
|
public @Nullable TYPE defaults() {
|
||||||
return this.defaultSupplier.get();
|
return this.defaultSupplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void defaults(@Nullable T defaultValue) {
|
public void defaults(@Nullable TYPE defaultValue) {
|
||||||
defaults(() -> defaultValue);
|
defaults(() -> defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void defaults(@NotNull Supplier<@Nullable T> defaultValue) {
|
public void defaults(@NotNull Supplier<@Nullable TYPE> defaultValue) {
|
||||||
this.defaultSupplier = defaultValue;
|
this.defaultSupplier = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDefaults() {
|
public boolean hasDefaults() {
|
||||||
return this.defaultSupplier.get() != null;
|
return defaults() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ValueValidator<UNIT> validator() {
|
||||||
|
return this.validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validator(@NotNull ValueValidator<UNIT> validator) {
|
||||||
|
this.validator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(@NotNull ValueValidator<UNIT> validator) {
|
||||||
|
validator(this.validator.and(validator));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UNIT withValidated(@Nullable UNIT value) throws Exception {
|
||||||
|
validator.validate(holder(), value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String path() {
|
public @NotNull String path() {
|
||||||
if (path != null) return path;
|
if (path != null) return path;
|
||||||
else throw new IllegalStateException("No section path provided.");
|
else throw new IllegalStateException("No section path provided for Value(" + type() + ").");
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfigurationHolder<?> holder() {
|
public @NotNull ConfigurationHolder<?> holder() {
|
||||||
if (this.holder != null) return this.holder;
|
if (this.holder != null) return this.holder;
|
||||||
throw new IllegalStateException("Value does not have a provider.");
|
throw new IllegalStateException("Value(" + type() + ") does not have a provider.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfigureSource<?, ?, ?> config() {
|
public @NotNull ConfigureSource<?, ?, ?> config() {
|
||||||
return holder().config();
|
return holder().config();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationMetaHolder metadata() {
|
public @NotNull ConfigurationMetaHolder metadata() {
|
||||||
return holder().metadata(path());
|
return holder().metadata(path());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object getData() {
|
@ApiStatus.Internal
|
||||||
|
protected @Nullable Object getData() {
|
||||||
return config().get(path());
|
return config().get(path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
protected void setData(@Nullable Object value) {
|
protected void setData(@Nullable Object value) {
|
||||||
config().set(path(), value);
|
config().set(path(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void throwing(@NotNull Throwable throwable) {
|
||||||
|
throwing(path, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, path) -> {
|
protected void throwing(@NotNull String path, @NotNull Throwable throwable) {
|
||||||
|
if (holder == null) throwable.printStackTrace();
|
||||||
|
else holder.throwing(path, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, valuePath) -> {
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import org.jetbrains.annotations.Contract;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
|
public abstract class CachedConfigValue<T, U> extends ConfigValue<T, U> {
|
||||||
|
|
||||||
protected @Nullable T cachedValue;
|
protected @Nullable T cachedValue;
|
||||||
protected long parsedTime = -1;
|
protected long parsedTime = -1;
|
||||||
|
|
||||||
protected CachedConfigValue(@NotNull ValueManifest<T> manifest) {
|
protected CachedConfigValue(@NotNull ValueManifest<T, U> manifest) {
|
||||||
super(manifest);
|
super(manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
package cc.carm.lib.configuration.value.impl;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueParser;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base implementation of a collection config value, like {@link List} or {@link Set}.
|
||||||
|
*
|
||||||
|
* @param <V> Value type
|
||||||
|
* @param <C> Collection type
|
||||||
|
* @param <SELF> Self reference type (used for internal call or recursive generics)
|
||||||
|
*/
|
||||||
|
public abstract class CollectionConfigValue<
|
||||||
|
V, C extends Collection<V>,
|
||||||
|
SELF extends CollectionConfigValue<V, C, SELF>
|
||||||
|
> extends CachedConfigValue<C, V> implements Collection<V> {
|
||||||
|
|
||||||
|
protected final @NotNull Supplier<? extends C> constructor;
|
||||||
|
protected final @NotNull ValueAdapter<V> paramAdapter;
|
||||||
|
|
||||||
|
public CollectionConfigValue(@NotNull ValueManifest<C, V> manifest,
|
||||||
|
@NotNull Supplier<? extends C> constructor,
|
||||||
|
@NotNull ValueAdapter<V> paramAdapter) {
|
||||||
|
super(manifest);
|
||||||
|
this.constructor = constructor;
|
||||||
|
this.paramAdapter = paramAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Adapter of this value.
|
||||||
|
*/
|
||||||
|
public @NotNull ValueAdapter<V> adapter() {
|
||||||
|
return this.paramAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ValueType<V> paramType() {
|
||||||
|
return adapter().type();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Value's parser, parse base object to value.
|
||||||
|
*/
|
||||||
|
public @Nullable ValueParser<V> parser() {
|
||||||
|
return parserFor(adapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Value's serializer, parse value to base object.
|
||||||
|
*/
|
||||||
|
public @Nullable ValueSerializer<V> serializer() {
|
||||||
|
return serializerFor(adapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull C createCollection() {
|
||||||
|
return constructor.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull C get() {
|
||||||
|
if (!cacheExpired()) return getCachedOrDefault(createCollection());
|
||||||
|
// Data that is outdated and needs to be parsed again.
|
||||||
|
C set = createCollection();
|
||||||
|
try {
|
||||||
|
List<?> data = config().contains(path()) ? config().getList(path()) : null;
|
||||||
|
if (data == null) return getDefaultFirst(set);
|
||||||
|
|
||||||
|
ValueParser<V> parser = parser();
|
||||||
|
if (parser == null) return getDefaultFirst(set);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Object dataVal : data) {
|
||||||
|
if (dataVal == null) continue;
|
||||||
|
try {
|
||||||
|
set.add(withValidated(parser.parse(holder(), paramType(), dataVal)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throwing(path + "[" + i + "]", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throwing(ex);
|
||||||
|
}
|
||||||
|
return updateCache(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(@Nullable C collection) {
|
||||||
|
updateCache(collection);
|
||||||
|
if (collection == null) {
|
||||||
|
setData(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueSerializer<V> serializer = serializer();
|
||||||
|
if (serializer == null) return;
|
||||||
|
|
||||||
|
List<Object> data = new ArrayList<>();
|
||||||
|
for (V val : collection) {
|
||||||
|
if (val == null) continue;
|
||||||
|
try {
|
||||||
|
data.add(serializer.serialize(holder(), paramType(), withValidated(val)));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throwing(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull C copy() {
|
||||||
|
C other = createCollection();
|
||||||
|
other.addAll(resolve());
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract @NotNull SELF self();
|
||||||
|
|
||||||
|
public <T> @NotNull T handle(Function<C, T> function) {
|
||||||
|
C list = resolve();
|
||||||
|
T result = function.apply(list);
|
||||||
|
set(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF modify(Consumer<C> consumer) {
|
||||||
|
C list = resolve();
|
||||||
|
consumer.accept(list);
|
||||||
|
set(list);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return resolve().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return resolve().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return resolve().contains(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<V> iterator() {
|
||||||
|
return resolve().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Object @NotNull [] toArray() {
|
||||||
|
return resolve().toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> T @NotNull [] toArray(@NotNull T[] a) {
|
||||||
|
return resolve().toArray(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(@NotNull Collection<?> c) {
|
||||||
|
return new HashSet<>(resolve()).containsAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(V v) {
|
||||||
|
handle(list -> list.add(v));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(@NotNull Collection<? extends V> c) {
|
||||||
|
return handle(list -> list.addAll(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return handle(list -> list.remove(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(@NotNull Collection<?> c) {
|
||||||
|
return handle(list -> list.removeAll(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(@NotNull Collection<?> c) {
|
||||||
|
return handle(list -> list.retainAll(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
modify(Collection::clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,112 +1,47 @@
|
|||||||
package cc.carm.lib.configuration.value.standard;
|
package cc.carm.lib.configuration.value.standard;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
import cc.carm.lib.configuration.adapter.ValueParser;
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.list.ConfigListBuilder;
|
import cc.carm.lib.configuration.builder.collection.SimpleCollectionCreator;
|
||||||
|
import cc.carm.lib.configuration.builder.list.ConfigListCreator;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements List<V> {
|
public class ConfiguredList<V> extends CollectionConfigValue<V, List<V>, ConfiguredList<V>> implements List<V> {
|
||||||
|
|
||||||
public static <T> @NotNull ConfigListBuilder<T> builderOf(@NotNull Class<T> type) {
|
public static <T> @NotNull ConfigListCreator<T> builderOf(@NotNull Class<T> type) {
|
||||||
return builderOf(ValueType.of(type));
|
return builderOf(ValueType.of(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> @NotNull ConfigListBuilder<T> builderOf(@NotNull ValueType<T> type) {
|
public static <T> @NotNull ConfigListCreator<T> builderOf(@NotNull ValueType<T> type) {
|
||||||
return new ConfigListBuilder<>(type);
|
return new ConfigListCreator<>(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final @NotNull Supplier<? extends List<V>> constructor;
|
public static <T>
|
||||||
protected final @NotNull ValueAdapter<V> paramAdapter;
|
@NotNull SimpleCollectionCreator.Source<Object, T, List<T>, ConfiguredList<T>> with(@NotNull Class<T> registeredType) {
|
||||||
|
return with(ValueType.of(registeredType));
|
||||||
|
}
|
||||||
|
|
||||||
public ConfiguredList(@NotNull ValueManifest<List<V>> manifest,
|
public static <T> @NotNull SimpleCollectionCreator.Source<Object, T, List<T>, ConfiguredList<T>> with(@NotNull ValueType<T> registeredType) {
|
||||||
|
return builderOf(registeredType).fromObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> @NotNull ConfiguredList<T> of(@NotNull T value, @NotNull T... values) {
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
list.add(value);
|
||||||
|
Collections.addAll(list, values);
|
||||||
|
return with(ValueType.of(value)).defaults(list).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfiguredList(@NotNull ValueManifest<List<V>, V> manifest,
|
||||||
@NotNull Supplier<? extends List<V>> constructor,
|
@NotNull Supplier<? extends List<V>> constructor,
|
||||||
@NotNull ValueAdapter<V> paramAdapter) {
|
@NotNull ValueAdapter<V> paramAdapter) {
|
||||||
super(manifest);
|
super(manifest, constructor, paramAdapter);
|
||||||
this.constructor = constructor;
|
|
||||||
this.paramAdapter = paramAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Adapter of this value.
|
|
||||||
*/
|
|
||||||
public @NotNull ValueAdapter<V> adapter() {
|
|
||||||
return this.paramAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ValueType<V> paramType() {
|
|
||||||
return adapter().type();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Value's parser, parse base object to value.
|
|
||||||
*/
|
|
||||||
public @Nullable ValueParser<V> parser() {
|
|
||||||
return parserFor(adapter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Value's serializer, parse value to base object.
|
|
||||||
*/
|
|
||||||
public @Nullable ValueSerializer<V> serializer() {
|
|
||||||
return serializerFor(adapter());
|
|
||||||
}
|
|
||||||
|
|
||||||
private @NotNull List<V> createList() {
|
|
||||||
return constructor.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull List<V> get() {
|
|
||||||
if (!cacheExpired()) return getCachedOrDefault(createList());
|
|
||||||
// Data that is outdated and needs to be parsed again.
|
|
||||||
List<V> list = createList();
|
|
||||||
List<?> data = config().contains(path()) ? config().getList(path()) : null;
|
|
||||||
if (data == null) return getDefaultFirst(list);
|
|
||||||
|
|
||||||
ValueParser<V> parser = parser();
|
|
||||||
if (parser == null) return getDefaultFirst(list);
|
|
||||||
|
|
||||||
for (Object dataVal : data) {
|
|
||||||
if (dataVal == null) continue;
|
|
||||||
try {
|
|
||||||
list.add(parser.parse(holder(), paramType(), dataVal));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return updateCache(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@Nullable List<V> value) {
|
|
||||||
updateCache(value);
|
|
||||||
if (value == null) {
|
|
||||||
setData(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueSerializer<V> serializer = serializer();
|
|
||||||
if (serializer == null) return;
|
|
||||||
List<Object> data = new ArrayList<>();
|
|
||||||
for (V val : value) {
|
|
||||||
if (val == null) continue;
|
|
||||||
try {
|
|
||||||
data.add(serializer.serialize(holder(), paramType(), val));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -114,21 +49,8 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
return resolve().get(index);
|
return resolve().get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull List<V> copy() {
|
@Override
|
||||||
return new ArrayList<>(resolve());
|
public @NotNull ConfiguredList<V> self() {
|
||||||
}
|
|
||||||
|
|
||||||
public <T> @NotNull T handle(Function<List<V>, T> function) {
|
|
||||||
List<V> list = resolve();
|
|
||||||
T result = function.apply(list);
|
|
||||||
set(list);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ConfiguredList<V> modify(Consumer<List<V>> consumer) {
|
|
||||||
List<V> list = resolve();
|
|
||||||
consumer.accept(list);
|
|
||||||
set(list);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,89 +59,22 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
return handle(list -> list.set(index, element));
|
return handle(list -> list.set(index, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return resolve().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return resolve().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(Object o) {
|
|
||||||
return resolve().contains(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Iterator<V> iterator() {
|
|
||||||
return resolve().iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Object @NotNull [] toArray() {
|
|
||||||
return resolve().toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public <T> T @NotNull [] toArray(@NotNull T[] a) {
|
|
||||||
return resolve().toArray(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(@NotNull Collection<?> c) {
|
|
||||||
return new HashSet<>(resolve()).containsAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean add(V v) {
|
|
||||||
handle(list -> list.add(v));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(int index, V element) {
|
public void add(int index, V element) {
|
||||||
modify(list -> list.add(index, element));
|
modify(list -> list.add(index, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(@NotNull Collection<? extends V> c) {
|
|
||||||
return handle(list -> list.addAll(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(int index, @NotNull Collection<? extends V> c) {
|
public boolean addAll(int index, @NotNull Collection<? extends V> c) {
|
||||||
return handle(list -> list.addAll(index, c));
|
return handle(list -> list.addAll(index, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
return handle(list -> list.remove(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V remove(int index) {
|
public V remove(int index) {
|
||||||
return handle(list -> list.remove(index));
|
return handle(list -> list.remove(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(@NotNull Collection<?> c) {
|
|
||||||
return handle(list -> list.removeAll(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(@NotNull Collection<?> c) {
|
|
||||||
return handle(list -> list.retainAll(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
modify(List::clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
@@ -249,4 +104,5 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
return resolve().subList(fromIndex, toIndex);
|
return resolve().subList(fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import cc.carm.lib.configuration.adapter.ValueParser;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.map.ConfigMapCreator;
|
import cc.carm.lib.configuration.builder.map.ConfigMapCreator;
|
||||||
|
import cc.carm.lib.configuration.builder.map.SourceMapBuilder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
||||||
@@ -17,7 +18,11 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements Map<K, V> {
|
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>, V> implements Map<K, V> {
|
||||||
|
|
||||||
|
public static <V> ConfigMapCreator<String, V> builderOf(@NotNull Class<V> valueType) {
|
||||||
|
return builderOf(String.class, valueType);
|
||||||
|
}
|
||||||
|
|
||||||
public static <K, V> ConfigMapCreator<K, V> builderOf(@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
|
public static <K, V> ConfigMapCreator<K, V> builderOf(@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
|
||||||
return new ConfigMapCreator<>(keyType, valueType);
|
return new ConfigMapCreator<>(keyType, valueType);
|
||||||
@@ -27,6 +32,16 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
|||||||
return new ConfigMapCreator<>(ValueType.of(keyType), ValueType.of(valueType));
|
return new ConfigMapCreator<>(ValueType.of(keyType), ValueType.of(valueType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @NotNull <K, V>
|
||||||
|
SourceMapBuilder<LinkedHashMap<K, V>, Object, K, V> with(@NotNull Class<K> keyType, @NotNull Class<V> valueType) {
|
||||||
|
return with(ValueType.of(keyType), ValueType.of(valueType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull <K, V>
|
||||||
|
SourceMapBuilder<LinkedHashMap<K, V>, Object, K, V> with(@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
|
||||||
|
return new ConfigMapCreator<>(keyType, valueType).asLinkedMap().fromObject();
|
||||||
|
}
|
||||||
|
|
||||||
public static <K, V> ConfiguredMap<K, V> of(@NotNull Supplier<? extends Map<K, V>> constructor,
|
public static <K, V> ConfiguredMap<K, V> of(@NotNull Supplier<? extends Map<K, V>> constructor,
|
||||||
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
|
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
|
||||||
return new ConfiguredMap<>(new ValueManifest<>(new ValueType<Map<K, V>>() {
|
return new ConfiguredMap<>(new ValueManifest<>(new ValueType<Map<K, V>>() {
|
||||||
@@ -38,7 +53,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
|||||||
protected final @NotNull ValueAdapter<K> keyAdapter;
|
protected final @NotNull ValueAdapter<K> keyAdapter;
|
||||||
protected final @NotNull ValueAdapter<V> valueAdapter;
|
protected final @NotNull ValueAdapter<V> valueAdapter;
|
||||||
|
|
||||||
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>> manifest,
|
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>, V> manifest,
|
||||||
@NotNull Supplier<? extends Map<K, V>> constructor,
|
@NotNull Supplier<? extends Map<K, V>> constructor,
|
||||||
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
|
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
|
||||||
super(manifest);
|
super(manifest);
|
||||||
@@ -73,26 +88,31 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
|||||||
// If the value is expired, we need to update it
|
// If the value is expired, we need to update it
|
||||||
Map<K, V> map = createMap();
|
Map<K, V> map = createMap();
|
||||||
|
|
||||||
ConfigureSection section = config().getSection(path());
|
try {
|
||||||
if (section == null) return getDefaultFirst(map);
|
ConfigureSection section = config().getSection(path());
|
||||||
|
if (section == null) return getDefaultFirst(map);
|
||||||
|
|
||||||
Set<String> keys = section.getKeys(false);
|
Set<String> keys = section.getKeys(false);
|
||||||
if (keys.isEmpty()) return getDefaultFirst(map);
|
if (keys.isEmpty()) return getDefaultFirst(map);
|
||||||
|
|
||||||
ValueParser<K> keyParser = parserFor(keyAdapter);
|
ValueParser<K> keyParser = parserFor(keyAdapter);
|
||||||
ValueParser<V> valueParser = parserFor(valueAdapter);
|
if (keyParser == null) return getDefaultFirst(map);
|
||||||
if (keyParser == null || valueParser == null) return getDefaultFirst(map);
|
ValueParser<V> valueParser = parserFor(valueAdapter);
|
||||||
|
if (valueParser == null) return getDefaultFirst(map);
|
||||||
|
|
||||||
for (String dataKey : keys) {
|
for (String dataKey : keys) {
|
||||||
Object dataVal = section.get(dataKey);
|
Object dataVal = section.get(dataKey);
|
||||||
if (dataVal == null) continue;
|
if (dataVal == null) continue;
|
||||||
try {
|
try {
|
||||||
K key = keyParser.parse(holder(), keyType(), dataKey);
|
K key = keyParser.parse(holder(), keyType(), dataKey);
|
||||||
V value = valueParser.parse(holder(), valueType(), dataVal);
|
V value = valueParser.parse(holder(), valueType(), dataVal);
|
||||||
map.put(key, value);
|
map.put(key, withValidated(value));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throwing(path + "." + dataKey, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throwing(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateCache(map);
|
return updateCache(map);
|
||||||
@@ -115,23 +135,28 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueSerializer<K> keySerializer = serializerFor(keyAdapter);
|
try {
|
||||||
ValueSerializer<V> valueSerializer = serializerFor(valueAdapter);
|
ValueSerializer<K> keySerializer = serializerFor(keyAdapter);
|
||||||
if (keySerializer == null || valueSerializer == null) return;
|
if (keySerializer == null) return;
|
||||||
|
ValueSerializer<V> valueSerializer = serializerFor(valueAdapter);
|
||||||
|
if (valueSerializer == null) return;
|
||||||
|
|
||||||
Map<Object, Object> data = new LinkedHashMap<>();
|
Map<Object, Object> data = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (Map.Entry<K, V> entry : value.entrySet()) {
|
for (Map.Entry<K, V> entry : value.entrySet()) {
|
||||||
try {
|
try {
|
||||||
data.put(
|
data.put(
|
||||||
keySerializer.serialize(holder(), keyType(), entry.getKey()),
|
keySerializer.serialize(holder(), keyType(), entry.getKey()),
|
||||||
valueSerializer.serialize(holder(), valueType(), entry.getValue())
|
valueSerializer.serialize(holder(), valueType(), withValidated(entry.getValue()))
|
||||||
);
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throwing(path + "." + entry.getKey(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setData(data);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throwing(ex);
|
||||||
}
|
}
|
||||||
setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> @NotNull T handle(Function<Map<K, V>, T> function) {
|
public <T> @NotNull T handle(Function<Map<K, V>, T> function) {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import cc.carm.lib.configuration.adapter.ValueParser;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.value.ConfigValueBuilder;
|
import cc.carm.lib.configuration.builder.value.ConfigValueBuilder;
|
||||||
|
import cc.carm.lib.configuration.builder.value.SourceValueBuilder;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -12,16 +14,54 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
public class ConfiguredValue<V> extends CachedConfigValue<V, V> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new value builder.
|
||||||
|
*
|
||||||
|
* @param type The type of the value.
|
||||||
|
* @param <V> The type of the value.
|
||||||
|
* @return a {@link ConfigValueBuilder} with the specified type.
|
||||||
|
*/
|
||||||
public static <V> ConfigValueBuilder<V> builderOf(@NotNull Class<V> type) {
|
public static <V> ConfigValueBuilder<V> builderOf(@NotNull Class<V> type) {
|
||||||
return new ConfigValueBuilder<>(ValueType.of(type));
|
return new ConfigValueBuilder<>(ValueType.of(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new value builder.
|
||||||
|
*
|
||||||
|
* @param type The type of the value.
|
||||||
|
* @param <V> The type of the value.
|
||||||
|
* @return a {@link ConfigValueBuilder} with the specified type.
|
||||||
|
*/
|
||||||
public static <V> ConfigValueBuilder<V> builderOf(@NotNull ValueType<V> type) {
|
public static <V> ConfigValueBuilder<V> builderOf(@NotNull ValueType<V> type) {
|
||||||
return new ConfigValueBuilder<>(type);
|
return new ConfigValueBuilder<>(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new value builder with the specified {@link ConfigurationHolder#registeredValues()} type.
|
||||||
|
*
|
||||||
|
* @param registeredType The type of the value.
|
||||||
|
* @param <V> The type of the value.
|
||||||
|
* @return a {@link SourceValueBuilder} with the specified registered type.
|
||||||
|
* @see ValueAdapter
|
||||||
|
*/
|
||||||
|
public static <V> SourceValueBuilder<V, V> with(@NotNull Class<V> registeredType) {
|
||||||
|
return with(ValueType.of(registeredType));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new value builder with the specified {@link ConfigurationHolder#registeredValues()} type.
|
||||||
|
*
|
||||||
|
* @param registeredType The type of the value.
|
||||||
|
* @param <V> The type of the value.
|
||||||
|
* @return a {@link SourceValueBuilder} with the specified registered type.
|
||||||
|
* @see ValueAdapter
|
||||||
|
*/
|
||||||
|
public static <V> SourceValueBuilder<V, V> with(@NotNull ValueType<V> registeredType) {
|
||||||
|
return new ConfigValueBuilder<>(registeredType).from(registeredType);
|
||||||
|
}
|
||||||
|
|
||||||
public static <V> ConfiguredValue<V> of(@NotNull V defaults) {
|
public static <V> ConfiguredValue<V> of(@NotNull V defaults) {
|
||||||
return of(ValueType.of(defaults), () -> defaults);
|
return of(ValueType.of(defaults), () -> defaults);
|
||||||
}
|
}
|
||||||
@@ -45,13 +85,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
|
|
||||||
public static <V> ConfiguredValue<V> of(@NotNull ValueType<V> type, @NotNull Supplier<@Nullable V> defaultSupplier) {
|
public static <V> ConfiguredValue<V> of(@NotNull ValueType<V> type, @NotNull Supplier<@Nullable V> defaultSupplier) {
|
||||||
return of(
|
return of(
|
||||||
new ValueManifest<>(type, defaultSupplier),
|
new ValueManifest<>(type, defaultSupplier),
|
||||||
(provider, t, data) -> provider.deserialize(type, data),
|
(provider, t, data) -> provider.deserialize(type, data),
|
||||||
(provider, t, value) -> provider.serialize(value)
|
(provider, t, value) -> provider.serialize(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest,
|
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V, V> manifest,
|
||||||
@Nullable ValueParser<V> parser,
|
@Nullable ValueParser<V> parser,
|
||||||
@Nullable ValueSerializer<V> serializer) {
|
@Nullable ValueSerializer<V> serializer) {
|
||||||
ValueAdapter<V> adapter = new ValueAdapter<>(manifest.type());
|
ValueAdapter<V> adapter = new ValueAdapter<>(manifest.type());
|
||||||
@@ -60,13 +100,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
return of(manifest, adapter);
|
return of(manifest, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
|
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V, V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||||
return new ConfiguredValue<>(manifest, adapter);
|
return new ConfiguredValue<>(manifest, adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final @NotNull ValueAdapter<V> adapter;
|
protected final @NotNull ValueAdapter<V> adapter;
|
||||||
|
|
||||||
public ConfiguredValue(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
|
public ConfiguredValue(@NotNull ValueManifest<V, V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||||
super(manifest);
|
super(manifest);
|
||||||
this.adapter = adapter;
|
this.adapter = adapter;
|
||||||
}
|
}
|
||||||
@@ -97,18 +137,19 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
if (!cacheExpired()) return getCachedOrDefault();
|
if (!cacheExpired()) return getCachedOrDefault();
|
||||||
// Data that is outdated and needs to be parsed again.
|
// Data that is outdated and needs to be parsed again.
|
||||||
|
|
||||||
Object data = getData();
|
|
||||||
if (data == null) return defaults();
|
|
||||||
|
|
||||||
ValueParser<V> parser = parser();
|
|
||||||
if (parser == null) return defaults(); // No parser, return default value.
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Object data = getData();
|
||||||
|
if (data == null) return defaults();
|
||||||
|
|
||||||
|
ValueParser<V> parser = parser();
|
||||||
|
if (parser == null) return defaults(); // No parser, return default value.
|
||||||
|
|
||||||
// If there are no errors, update the cache and return.
|
// If there are no errors, update the cache and return.
|
||||||
return updateCache(parser.parse(holder(), type(), data));
|
V parsed = parser.parse(holder(), type(), data);
|
||||||
|
return updateCache(withValidated(parsed));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// There was a parsing error, prompted and returned the default value.
|
// There was a validate or parsing error, prompted and returned the default value.
|
||||||
e.printStackTrace();
|
throwing(e);
|
||||||
return defaults();
|
return defaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,20 +162,20 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
* @param value The value to be set
|
* @param value The value to be set
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void set(V value) {
|
public void set(@Nullable V value) {
|
||||||
updateCache(value); // Update cache
|
updateCache(value); // Update cache
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
setData(null);
|
setData(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueSerializer<V> serializer = serializer();
|
|
||||||
if (serializer == null) return; // No serializer, do nothing.
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setData(serializer.serialize(holder(), type(), value));
|
ValueSerializer<V> serializer = serializer();
|
||||||
|
if (serializer == null) return; // No serializer, do nothing.
|
||||||
|
|
||||||
|
setData(serializer.serialize(holder(), type(), withValidated(value)));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throwing(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
//import java.util.LinkedList;
|
//import java.util.LinkedList;
|
||||||
//import java.util.List;
|
//import java.util.List;
|
||||||
//
|
//
|
||||||
///**
|
/// **
|
||||||
// * @author Chris2018998
|
// * @author Chris2018998
|
||||||
// */
|
// */
|
||||||
//public class OffsetUtil {
|
//public class OffsetUtil {
|
||||||
@@ -25,15 +25,15 @@
|
|||||||
// } catch (NoSuchFieldException | IllegalAccessException e) {
|
// } catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
// }
|
// }
|
||||||
//// try {
|
/// / try {
|
||||||
//// unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
|
/// / unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
|
||||||
//// Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
/// / Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
//// theUnsafe.setAccessible(true);
|
/// / theUnsafe.setAccessible(true);
|
||||||
//// return (Unsafe) theUnsafe.get(null);
|
/// / return (Unsafe) theUnsafe.get(null);
|
||||||
//// });
|
/// / });
|
||||||
//// } catch (Throwable e) {
|
/// / } catch (Throwable e) {
|
||||||
//// System.err.println("Unable to load unsafe");
|
/// / System.err.println("Unable to load unsafe");
|
||||||
//// }
|
/// / }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
|
// public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
|
||||||
|
|||||||
+174
-11
@@ -3,9 +3,9 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>configured-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>4.0.7</version>
|
<version>4.2.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -13,34 +13,132 @@
|
|||||||
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||||
|
<maven.deploy.skip>true</maven.deploy.skip>
|
||||||
|
|
||||||
|
<deps.mysql-driver.version>8.0.33</deps.mysql-driver.version>
|
||||||
|
<log4j.version>2.26.0</log4j.version>
|
||||||
</properties>
|
</properties>
|
||||||
<artifactId>easyconfiguration-demo</artifactId>
|
<artifactId>configured-demo</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Configured - Demo</name>
|
||||||
|
<url>https://github.com/CarmJos/configured</url>
|
||||||
|
<description>Demonstrate & tests module.</description>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.parent.groupId}</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.parent.groupId}</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-feature-commentable</artifactId>
|
<artifactId>configured-feature-commentable</artifactId>
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
<scope>compile</scope>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-feature-versioned</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-feature-validators</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-feature-kotlin</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-yaml</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-gson</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-sql</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<artifactId>easysql-beecp</artifactId>
|
||||||
|
<version>0.4.7</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>${deps.mysql-driver.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-mongodb</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>configured-hocon</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-core</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-slf4j-impl</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
@@ -53,6 +151,71 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-maven-plugin</artifactId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>compile</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sourceDirs>
|
||||||
|
<source>src/main/java</source>
|
||||||
|
<source>target/generated-sources/annotations</source>
|
||||||
|
</sourceDirs>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>test-compile</id>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test-compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<jvmTarget>1.8</jvmTarget>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-compile</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>default-testCompile</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>compile</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>testCompile</id>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@ package cc.carm.lib.configuration.demo;
|
|||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComments;
|
import cc.carm.lib.configuration.annotation.HeaderComments;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
|
||||||
@HeaderComments({"", "数据库配置", " 用于提供数据库连接,进行数据库操作。"})
|
@HeaderComments({"", "数据库配置", " 用于提供数据库连接,进行数据库操作。"})
|
||||||
public class DatabaseConfiguration implements Configuration {
|
public interface DatabaseConfiguration extends Configuration {
|
||||||
|
|
||||||
@ConfigPath("driver")
|
@ConfigPath("driver")
|
||||||
@HeaderComments({
|
@HeaderComments({
|
||||||
"数据库驱动配置,请根据数据库类型设置。",
|
"数据库驱动配置,请根据数据库类型设置。",
|
||||||
"- MySQL(旧): com.mysql.jdbc.Driver",
|
"- MySQL(旧): com.mysql.jdbc.Driver",
|
||||||
"- MySQL(新): com.mysql.cj.jdbc.Driver",
|
"- MySQL(新): com.mysql.cj.jdbc.Driver",
|
||||||
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
|
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
|
||||||
})
|
})
|
||||||
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
|
ConfiguredValue<String> DRIVER_NAME = ConfiguredValue.of(
|
||||||
String.class, "com.mysql.cj.jdbc.Driver"
|
String.class, "com.mysql.cj.jdbc.Driver"
|
||||||
);
|
);
|
||||||
|
|
||||||
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
|
ConfiguredValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
|
||||||
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
|
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
|
||||||
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
|
ConfiguredValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
|
||||||
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
|
ConfiguredValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
|
||||||
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
|
ConfiguredValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
|
||||||
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
|
|
||||||
|
|
||||||
protected static String buildJDBC() {
|
ConfiguredValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
|
||||||
|
|
||||||
|
static String buildJDBC() {
|
||||||
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
|
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests;
|
package cc.carm.lib.configuration.demo.tests;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.conf.KotlinConfiguration;
|
||||||
import cc.carm.lib.configuration.demo.tests.conf.RegistryConfig;
|
import cc.carm.lib.configuration.demo.tests.conf.RegistryConfig;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
import org.jetbrains.annotations.TestOnly;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -69,17 +71,34 @@ public class ConfigurationTest {
|
|||||||
provider.initialize(TEST);
|
provider.initialize(TEST);
|
||||||
|
|
||||||
System.out.println("> Test Inner value before:");
|
System.out.println("> Test Inner value before:");
|
||||||
System.out.println(TEST.INSTANCE.INNER_VALUE.resolve());
|
System.out.println(TEST.INSTANCE.STATUS.resolve());
|
||||||
|
|
||||||
double after = Math.random() * 200D;
|
double after = Math.random() * 200D;
|
||||||
System.out.println("> Test Inner value -> " + after);
|
System.out.println("> Test Inner value -> " + after);
|
||||||
TEST.INSTANCE.INNER_VALUE.set(after);
|
TEST.INSTANCE.STATUS.set(after);
|
||||||
|
|
||||||
System.out.println("> Test Inner value after:");
|
System.out.println("> Test Inner value after:");
|
||||||
System.out.println(TEST.INSTANCE.INNER_VALUE.resolve());
|
System.out.println(TEST.INSTANCE.STATUS.resolve());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void testKotlin(ConfigurationHolder<?> provider) {
|
||||||
|
provider.initialize(KotlinConfiguration.class);
|
||||||
|
|
||||||
|
System.out.println("> Test Kotlin value before:");
|
||||||
|
System.out.println(KotlinConfiguration.INSTANCE.getLINKED_MAP().get());
|
||||||
|
|
||||||
|
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("Language", "Kotlin");
|
||||||
|
System.out.println("> Test Kotlin value -> " + map);
|
||||||
|
KotlinConfiguration.INSTANCE.getLINKED_MAP().set(map);
|
||||||
|
|
||||||
|
System.out.println("> Test Kotlin value after:");
|
||||||
|
System.out.println(KotlinConfiguration.INSTANCE.getLINKED_MAP().get());
|
||||||
|
|
||||||
|
System.out.println("> Test Set value -> " + KotlinConfiguration.INSTANCE.getBLACK_LIST().get());
|
||||||
|
}
|
||||||
|
|
||||||
public static void save(ConfigurationHolder<?> provider) {
|
public static void save(ConfigurationHolder<?> provider) {
|
||||||
try {
|
try {
|
||||||
provider.save();
|
provider.save();
|
||||||
|
|||||||
+33
-35
@@ -1,14 +1,9 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests.conf;
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.*;
|
||||||
import cc.carm.lib.configuration.annotation.FooterComments;
|
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComments;
|
|
||||||
import cc.carm.lib.configuration.annotation.InlineComment;
|
|
||||||
import cc.carm.lib.configuration.demo.DatabaseConfiguration;
|
|
||||||
import cc.carm.lib.configuration.demo.tests.model.ItemStack;
|
import cc.carm.lib.configuration.demo.tests.model.ItemStack;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredMap;
|
import cc.carm.lib.configuration.value.standard.ConfiguredMap;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
@@ -21,49 +16,52 @@ import java.util.UUID;
|
|||||||
@ConfigPath(root = true)
|
@ConfigPath(root = true)
|
||||||
@HeaderComments({"此处内容将显示在配置文件的最上方"})
|
@HeaderComments({"此处内容将显示在配置文件的最上方"})
|
||||||
@FooterComments({
|
@FooterComments({
|
||||||
"------------------------------------------------",
|
"------------------------------------------------",
|
||||||
"此处内容将显示在配置文件的最下方",
|
"此处内容将显示在配置文件的最下方",
|
||||||
"可用于显示版权信息等",
|
"可用于显示版权信息等",
|
||||||
"感谢您使用 https://github.com/CarmJos/EasyConfiguration !"
|
"感谢您使用 https://github.com/CarmJos/configured !"
|
||||||
})
|
})
|
||||||
public interface DemoConfiguration extends Configuration {
|
public interface DemoConfiguration extends Configuration {
|
||||||
|
|
||||||
@ConfigPath(root = true)
|
@ConfigPath(root = true)
|
||||||
ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
@ConfigVersion(2)
|
||||||
|
ConfiguredValue<Double> VERSION = ConfiguredValue.of(Double.class, 2.0D);
|
||||||
|
|
||||||
@ConfigPath(root = true)
|
@ConfigPath(root = true)
|
||||||
@FooterComments({"此处内容将显示在配置条目的下方", "可用于补充说明,但一般不建议使用"})
|
@FooterComments({"此处内容将显示在配置条目的下方", "可用于补充说明,但一般不建议使用"})
|
||||||
ConfigValue<Long> TEST_NUMBER = ConfiguredValue.of(1000000L);
|
ConfiguredValue<Long> TEST_NUMBER = ConfiguredValue.with(Long.class).defaults(123456789L).build();
|
||||||
|
|
||||||
@HeaderComments({"枚举类型测试"})
|
@HeaderComments({"枚举类型测试"})
|
||||||
@FooterComments({"上述的枚举内容本质上是通过STRING解析的"})
|
@FooterComments({"上述的枚举内容本质上是通过STRING解析的"})
|
||||||
ConfigValue<ChronoUnit> TEST_ENUM = ConfiguredValue.of(ChronoUnit.class, ChronoUnit.DAYS);
|
ConfiguredValue<ChronoUnit> TEST_ENUM = ConfiguredValue.of(ChronoUnit.class, ChronoUnit.DAYS);
|
||||||
|
|
||||||
// 支持通过 Class<?> 变量标注子配置,一并注册。
|
@HeaderComments({"空值测试"})
|
||||||
// 注意: 若对应类也有注解,则优先使用类的注解。
|
@InlineComment("空值Inline注释")
|
||||||
Class<?> DATABASE = DatabaseConfiguration.class;
|
ConfiguredMap<String, String> EMPTY = ConfiguredMap.builderOf(String.class, String.class)
|
||||||
|
.asLinkedMap().fromString()
|
||||||
|
.build();
|
||||||
|
|
||||||
@ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComments({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComments({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("默认地注释会加到Section的首行末尾") // 通过注解给配置添加注释。
|
@InlineComment("默认地注释会加到Section的首行末尾") // 通过注解给配置添加注释。
|
||||||
ConfiguredList<UserRecord> ALLOWLISTS = ConfiguredList.builderOf(UserRecord.class).fromSection()
|
ConfiguredList<UserRecord> ALLOWLISTS = ConfiguredList.builderOf(UserRecord.class).fromSection()
|
||||||
.parse(UserRecord::deserialize).serialize(UserRecord::serialize)
|
.parse(UserRecord::deserialize).serialize(UserRecord::serialize)
|
||||||
.defaults(UserRecord.CARM).build();
|
.defaults(UserRecord.CARM).build();
|
||||||
|
|
||||||
@HeaderComments({
|
@HeaderComments({
|
||||||
"------------------------------------------------",
|
"------------------------------------------------",
|
||||||
"[ID - ItemStack]对照表", "", "用于测试Map类型的解析与序列化保存"
|
"[ID - ItemStack]对照表", "", "用于测试Map类型的解析与序列化保存"
|
||||||
})
|
})
|
||||||
@FooterComments("------------------------------------------------")
|
@FooterComments("------------------------------------------------")
|
||||||
ConfiguredMap<Integer, ItemStack> ITEMS = ConfiguredMap.builderOf(Integer.class, ItemStack.class)
|
ConfiguredMap<Integer, ItemStack> ITEMS = ConfiguredMap.builderOf(Integer.class, ItemStack.class)
|
||||||
.asLinkedMap().fromSection()
|
.asLinkedMap().fromSection()
|
||||||
.parseKey(data -> Integer.parseInt(data))
|
.parseKey(data -> Integer.parseInt(data))
|
||||||
.parse(ItemStack::deserialize).serialize(ItemStack::serialize)
|
.parse(ItemStack::deserialize).serialize(ItemStack::serialize)
|
||||||
.defaults(m -> {
|
.defaults(m -> {
|
||||||
m.put(1, new ItemStack("stone", 64));
|
m.put(1, new ItemStack("stone", 64));
|
||||||
m.put(2, new ItemStack("iron", 64, "铁锭", Arrays.asList("一些铁锭", "可以制造东西")));
|
m.put(2, new ItemStack("iron", 64, "铁锭", Arrays.asList("一些铁锭", "可以制造东西")));
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,19 +71,19 @@ public interface DemoConfiguration extends Configuration {
|
|||||||
class SUB implements Configuration {
|
class SUB implements Configuration {
|
||||||
|
|
||||||
@ConfigPath(value = "uuid-value", root = true)
|
@ConfigPath(value = "uuid-value", root = true)
|
||||||
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
public static final ConfiguredValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
||||||
.builderOf(UUID.class).fromString()
|
.builderOf(UUID.class).fromString()
|
||||||
.parse((holder, data) -> UUID.fromString(data))
|
.parse((holder, data) -> UUID.fromString(data))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@HeaderComments({"内部类的内部类测试", "通过这种方式,您可以轻易实现多层次的配置文件结构"})
|
@HeaderComments({"内部类的内部类测试", "通过这种方式,您可以轻易实现多层次的配置文件结构"})
|
||||||
@FooterComments({"-------------"})
|
@FooterComments({"-------------"})
|
||||||
public interface That extends Configuration {
|
public interface That extends Configuration {
|
||||||
|
|
||||||
ConfiguredList<UUID> OPERATORS = ConfiguredList
|
ConfiguredList<UUID> OPERATORS = ConfiguredList
|
||||||
.builderOf(UUID.class).fromString()
|
.builderOf(UUID.class).fromString()
|
||||||
.parse(s -> Objects.requireNonNull(UUID.fromString(s)))
|
.parse(s -> Objects.requireNonNull(UUID.fromString(s)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package cc.carm.lib.configuration.demo.tests.conf;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComments;
|
import cc.carm.lib.configuration.annotation.HeaderComments;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.annotation.ValueRange;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
|
||||||
@HeaderComments("Inner Test")
|
@HeaderComments("service")
|
||||||
public class InstanceConfig implements Configuration {
|
public class InstanceConfig implements Configuration {
|
||||||
|
|
||||||
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(1.0D);
|
@ValueRange(min = 0, max = 100, message = "The value must be between 0 and 100")
|
||||||
|
public final ConfiguredValue<Double> STATUS = ConfiguredValue.of(1.0D);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.conf
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.Configuration
|
||||||
|
import cc.carm.lib.configuration.annotation.ConfigPath
|
||||||
|
import cc.carm.lib.configuration.annotation.ConfigVersion
|
||||||
|
import cc.carm.lib.configuration.kotlin.value.*
|
||||||
|
|
||||||
|
@ConfigPath(root = true)
|
||||||
|
object KotlinConfiguration : Configuration {
|
||||||
|
@ConfigVersion(1)
|
||||||
|
val VERSION = valueFrom(Double::class) {
|
||||||
|
defaults(1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val USER_LIST = listFrom(String::class) {
|
||||||
|
defaults("Carm Jos")
|
||||||
|
}
|
||||||
|
|
||||||
|
val BLACK_LIST = setFrom(String::class) {
|
||||||
|
defaults("404", "404", "123")
|
||||||
|
}
|
||||||
|
|
||||||
|
val NICKNAME = mapFrom(String::class, ::mutableMapOf) {
|
||||||
|
defaultMap(mapOf("Carm Jos" to "Carm"))
|
||||||
|
parse { v -> v }
|
||||||
|
serialize { v -> v }
|
||||||
|
}
|
||||||
|
|
||||||
|
val LINKED_MAP = linkedMapFrom(String::class) {
|
||||||
|
parse { value ->
|
||||||
|
value
|
||||||
|
}
|
||||||
|
serialize { v -> v }
|
||||||
|
defaults("key", "value")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import cc.carm.lib.configuration.annotation.FooterComments;
|
|||||||
import cc.carm.lib.configuration.annotation.HeaderComments;
|
import cc.carm.lib.configuration.annotation.HeaderComments;
|
||||||
import cc.carm.lib.configuration.annotation.InlineComment;
|
import cc.carm.lib.configuration.annotation.InlineComment;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -20,10 +19,10 @@ public class RegistryConfig implements Configuration {
|
|||||||
@FooterComments({"12313213212"})
|
@FooterComments({"12313213212"})
|
||||||
@InlineComment(value = "用户名(匹配注释)", regex = "name") // 通过注解给配置添加注释。
|
@InlineComment(value = "用户名(匹配注释)", regex = "name") // 通过注解给配置添加注释。
|
||||||
@InlineComment(value = "信息", regex = {"info.*", "info.game.*"}) // 通过注解给配置添加注释。
|
@InlineComment(value = "信息", regex = {"info.*", "info.game.*"}) // 通过注解给配置添加注释。
|
||||||
public final ConfigValue<UserRecord> TEST_MODEL = ConfiguredValue.builderOf(UserRecord.class).fromSection()
|
public final ConfiguredValue<UserRecord> OWNER = ConfiguredValue.builderOf(UserRecord.class).fromSection()
|
||||||
.defaults(new UserRecord("Carm", UUID.randomUUID()))
|
.defaults(new UserRecord("Carm", UUID.randomUUID()))
|
||||||
.parse((holder, section) -> UserRecord.deserialize(section))
|
.parse((holder, section) -> UserRecord.deserialize(section))
|
||||||
.serialize((holder, data) -> data.serialize()).build();
|
.serialize((holder, data) -> data.serialize()).build();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ public class ItemStack {
|
|||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public @Nullable String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getLore() {
|
public @Nullable List<String> getLore() {
|
||||||
return lore;
|
return lore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ public class ItemStack {
|
|||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(@Nullable String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLore(List<String> lore) {
|
public void setLore(@Nullable List<String> lore) {
|
||||||
this.lore = lore;
|
this.lore = lore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,10 +69,10 @@ public class ItemStack {
|
|||||||
|
|
||||||
public static ItemStack deserialize(ConfigureSection section) {
|
public static ItemStack deserialize(ConfigureSection section) {
|
||||||
return new ItemStack(
|
return new ItemStack(
|
||||||
section.getString("material"),
|
section.getString("material"),
|
||||||
section.getInt("amount", 1),
|
section.getInt("amount", 1),
|
||||||
section.getString("name"),
|
section.getString("name"),
|
||||||
section.getStringList("lore")
|
section.getStringList("lore")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ public class UserRecord extends AbstractRecord {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TestUser{" +
|
return "TestUser{" +
|
||||||
"name='" + name + '\'' +
|
"name='" + name + '\'' +
|
||||||
", uuid=" + uuid +
|
", uuid=" + uuid +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-14
@@ -1,29 +1,21 @@
|
|||||||
package config;
|
package cc.carm.lib.configuration.tests.test;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
import cc.carm.lib.configuration.source.json.JSONConfigFactory;
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.source.json.JSONConfigFactory;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class JSONConfigTest {
|
public class JSONConfigTests {
|
||||||
|
|
||||||
protected final ConfigurationHolder<?> holder = JSONConfigFactory
|
protected final ConfigurationHolder<?> holder = JSONConfigFactory
|
||||||
.from(new File("target"), "config.json")
|
.from(new File("target"), "config.json")
|
||||||
.resourcePath("example.json")
|
.resourcePath("example.json")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onTest() {
|
public void onTest() {
|
||||||
|
|
||||||
ConfigValue<Boolean> EXAMPLE = ConfiguredValue.of(false);
|
|
||||||
EXAMPLE.initialize(this.holder, "example");
|
|
||||||
|
|
||||||
System.out.println("Example: " + EXAMPLE.get());
|
|
||||||
|
|
||||||
ConfigurationTest.testDemo(this.holder);
|
ConfigurationTest.testDemo(this.holder);
|
||||||
ConfigurationTest.testInner(this.holder);
|
ConfigurationTest.testInner(this.holder);
|
||||||
|
|
||||||
+14
-4
@@ -1,10 +1,11 @@
|
|||||||
package yaml.test;
|
package cc.carm.lib.configuration.tests.test;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.commentable.CommentableMeta;
|
import cc.carm.lib.configuration.commentable.CommentableMeta;
|
||||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
||||||
import cc.carm.lib.configuration.source.yaml.YAMLSource;
|
import cc.carm.lib.configuration.source.yaml.YAMLSource;
|
||||||
|
import cc.carm.lib.configuration.validators.Validators;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -13,15 +14,16 @@ import java.util.Map;
|
|||||||
public class YamlTests {
|
public class YamlTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() throws Exception {
|
||||||
|
|
||||||
ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/tests.yml")
|
ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/tests.yml")
|
||||||
.resourcePath("configs/sample.yml").build();
|
.resourcePath("configs/sample.yml").build();
|
||||||
|
|
||||||
|
Validators.activate(holder);
|
||||||
|
|
||||||
ConfigurationTest.testDemo(holder);
|
ConfigurationTest.testDemo(holder);
|
||||||
ConfigurationTest.testInner(holder);
|
ConfigurationTest.testInner(holder);
|
||||||
|
|
||||||
|
|
||||||
Map<String, List<String>> headers = holder.extractMetadata(CommentableMeta.HEADER);
|
Map<String, List<String>> headers = holder.extractMetadata(CommentableMeta.HEADER);
|
||||||
System.out.println("Header comments: ");
|
System.out.println("Header comments: ");
|
||||||
headers.forEach((k, v) -> {
|
headers.forEach((k, v) -> {
|
||||||
@@ -42,5 +44,13 @@ public class YamlTests {
|
|||||||
ConfigurationTest.save(holder);
|
ConfigurationTest.save(holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKotlin() {
|
||||||
|
ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/kotlin.yml").build();
|
||||||
|
|
||||||
|
ConfigurationTest.testKotlin(holder);
|
||||||
|
|
||||||
|
ConfigurationTest.save(holder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cc.carm.lib.configuration.tests.test.mongodb;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.Configuration;
|
||||||
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
|
||||||
|
interface MongoConfig extends Configuration {
|
||||||
|
ConfiguredValue<String> HOST = ConfiguredValue.of("127.0.0.1");
|
||||||
|
ConfiguredValue<Integer> PORT = ConfiguredValue.of(27017);
|
||||||
|
ConfiguredValue<String> USERNAME = ConfiguredValue.of("minecraft");
|
||||||
|
ConfiguredValue<String> PASSWORD = ConfiguredValue.of("minecraft");
|
||||||
|
ConfiguredValue<String> DATABASE = ConfiguredValue.of("minecraft");
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package cc.carm.lib.configuration.tests.test.mongodb;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.json.JSONConfigFactory;
|
||||||
|
import cc.carm.lib.configuration.source.mongodb.MongoConfigFactory;
|
||||||
|
import com.mongodb.ConnectionString;
|
||||||
|
import com.mongodb.MongoClientSettings;
|
||||||
|
import com.mongodb.MongoCredential;
|
||||||
|
import com.mongodb.client.MongoClient;
|
||||||
|
import com.mongodb.client.MongoClients;
|
||||||
|
import com.mongodb.client.MongoDatabase;
|
||||||
|
import org.bson.UuidRepresentation;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class MongoTest {
|
||||||
|
|
||||||
|
boolean local = false;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
if (!local) return;
|
||||||
|
|
||||||
|
ConfigurationHolder<?> gsonHolder = JSONConfigFactory.from(new File("target/mongo.json")).build();
|
||||||
|
gsonHolder.initialize(MongoConfig.class);
|
||||||
|
|
||||||
|
MongoClientSettings settings = MongoClientSettings.builder()
|
||||||
|
.applyConnectionString(new ConnectionString(
|
||||||
|
"mongodb://" + MongoConfig.HOST.resolve() + ":" + MongoConfig.PORT.resolve()
|
||||||
|
))
|
||||||
|
.credential(MongoCredential.createCredential(
|
||||||
|
MongoConfig.USERNAME.resolve(), MongoConfig.DATABASE.resolve(),
|
||||||
|
MongoConfig.PASSWORD.resolve().toCharArray()
|
||||||
|
))
|
||||||
|
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||||
|
.build();
|
||||||
|
MongoClient mongoClient = MongoClients.create(settings);
|
||||||
|
MongoDatabase mongoDatabase = mongoClient.getDatabase(MongoConfig.DATABASE.resolve());
|
||||||
|
|
||||||
|
ConfigurationHolder<?> mongoHolder = MongoConfigFactory
|
||||||
|
.from(mongoDatabase, "configs")
|
||||||
|
.namespace("my_plugin")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Test the configuration
|
||||||
|
ConfigurationTest.testDemo(mongoHolder);
|
||||||
|
ConfigurationTest.testInner(mongoHolder);
|
||||||
|
|
||||||
|
ConfigurationTest.save(mongoHolder);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package cc.carm.lib.configuration.tests.test.sql;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.demo.DatabaseConfiguration;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.json.JSONConfigFactory;
|
||||||
|
import cc.carm.lib.configuration.source.sql.SQLConfigFactory;
|
||||||
|
import cc.carm.lib.easysql.EasySQL;
|
||||||
|
import cc.carm.lib.easysql.api.SQLManager;
|
||||||
|
import cc.carm.lib.easysql.beecp.BeeDataSourceConfig;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class SQLConfigTest {
|
||||||
|
|
||||||
|
boolean local = false;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
if (!local) return;
|
||||||
|
|
||||||
|
ConfigurationHolder<?> gsonHolder = JSONConfigFactory.from(new File("target/sql.json")).build();
|
||||||
|
gsonHolder.initialize(DatabaseConfiguration.class);
|
||||||
|
|
||||||
|
BeeDataSourceConfig config = new BeeDataSourceConfig();
|
||||||
|
config.setDriverClassName(DatabaseConfiguration.DRIVER_NAME.resolve());
|
||||||
|
config.setJdbcUrl(DatabaseConfiguration.buildJDBC());
|
||||||
|
config.setUsername(DatabaseConfiguration.USERNAME.resolve());
|
||||||
|
config.setPassword(DatabaseConfiguration.PASSWORD.resolve());
|
||||||
|
|
||||||
|
SQLManager manager = EasySQL.createManager(config);
|
||||||
|
manager.setDebugMode(true);
|
||||||
|
|
||||||
|
ConfigurationHolder<?> holder = SQLConfigFactory.from(manager)
|
||||||
|
.tableName("test_configs")
|
||||||
|
.namespace("testing")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ConfigurationTest.testDemo(holder);
|
||||||
|
ConfigurationTest.testInner(holder);
|
||||||
|
|
||||||
|
ConfigurationTest.save(holder);
|
||||||
|
|
||||||
|
EasySQL.shutdownManager(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Configuration status="WARN" packages="config.SQLConfigTest">
|
<Configuration status="WARN" packages="cc.carm.lib.configuration.tests">
|
||||||
<Appenders>
|
<Appenders>
|
||||||
<console name="Console" target="SYSTEM_OUT">
|
<console name="Console" target="SYSTEM_OUT">
|
||||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n"/>
|
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n"/>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<artifactId>configured-parent</artifactId>
|
||||||
|
<version>4.2.1</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<artifactId>configured-feature-collections</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Configured - Collections Feature</name>
|
||||||
|
<url>https://github.com/CarmJos/configured</url>
|
||||||
|
<description>Provides more collection type support for the Configured framework.</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>configured-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>configured-gson</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
package cc.carm.lib.configuration.builder.set;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.collection.SectionCollectionBuilder;
|
||||||
|
import cc.carm.lib.configuration.builder.collection.SourceCollectionBuilder;
|
||||||
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.value.collections.ConfiguredSet;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ConfigSetBuilder<V> {
|
||||||
|
|
||||||
|
protected final @NotNull ValueType<V> type;
|
||||||
|
|
||||||
|
public ConfigSetBuilder(@NotNull ValueType<V> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S> @NotNull SourceBuilder<S, V> from(@NotNull Class<S> sourceType) {
|
||||||
|
return from(ValueType.of(sourceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S> @NotNull SourceBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
||||||
|
return new SourceBuilder<>(
|
||||||
|
sourceType, type,
|
||||||
|
ValueHandler.required(type),
|
||||||
|
ValueHandler.required(sourceType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigSetBuilder.SourceBuilder<Object, V> fromObject() {
|
||||||
|
return new SourceBuilder<>(
|
||||||
|
ValueType.OBJECT, type,
|
||||||
|
ValueHandler.deserialize(type), ValueHandler.toObject()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigSetBuilder.SourceBuilder<String, V> fromString() {
|
||||||
|
return new SourceBuilder<>(
|
||||||
|
ValueType.STRING, type,
|
||||||
|
ValueHandler.required(type), ValueHandler.stringValue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigSetBuilder.SectionBuilder<V> fromSection() {
|
||||||
|
return new SectionBuilder<>(type, ValueHandler.required(type), ValueHandler.required());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class SourceBuilder<SOURCE, V> extends SourceCollectionBuilder<SOURCE, V, Set<V>, ConfiguredSet<V>, SourceBuilder<SOURCE, V>> {
|
||||||
|
|
||||||
|
public SourceBuilder(@NotNull ValueType<SOURCE> sourceType,
|
||||||
|
@NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<SOURCE, V> parser,
|
||||||
|
@NotNull ValueHandler<V, SOURCE> serializer) {
|
||||||
|
super(LinkedHashSet::new, sourceType, paramType, parser, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull ConfigSetBuilder.SourceBuilder<SOURCE, V> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredSet<V> build() {
|
||||||
|
return new ConfiguredSet<>(buildManifest(), constructor, buildAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SectionBuilder<V> extends SectionCollectionBuilder<V, Set<V>, ConfiguredSet<V>, SectionBuilder<V>> {
|
||||||
|
|
||||||
|
public SectionBuilder(@NotNull ValueType<V> paramType,
|
||||||
|
@NotNull ValueHandler<ConfigureSection, V> parser,
|
||||||
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
|
||||||
|
super(LinkedHashSet::new, paramType, parser, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull ConfigSetBuilder.SectionBuilder<V> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredSet<V> build() {
|
||||||
|
return new ConfiguredSet<>(buildManifest(), constructor, buildAdapter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package cc.carm.lib.configuration.value.collections;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.set.ConfigSetBuilder;
|
||||||
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
|
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ConfiguredSet<V> extends CollectionConfigValue<V, Set<V>, ConfiguredSet<V>> implements Set<V> {
|
||||||
|
|
||||||
|
public static <T> @NotNull ConfigSetBuilder<T> builderOf(@NotNull Class<T> type) {
|
||||||
|
return builderOf(ValueType.of(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> @NotNull ConfigSetBuilder<T> builderOf(@NotNull ValueType<T> type) {
|
||||||
|
return new ConfigSetBuilder<>(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> @NotNull ConfigSetBuilder.SourceBuilder<Object, T> with(@NotNull Class<T> registeredType) {
|
||||||
|
return with(ValueType.of(registeredType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> @NotNull ConfigSetBuilder.SourceBuilder<Object, T> with(@NotNull ValueType<T> registeredType) {
|
||||||
|
return builderOf(registeredType).fromObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> @NotNull ConfiguredSet<T> of(@NotNull T value, @NotNull T... values) {
|
||||||
|
Set<T> list = new LinkedHashSet<>();
|
||||||
|
list.add(value);
|
||||||
|
Collections.addAll(list, values);
|
||||||
|
return with(ValueType.of(value)).defaults(list).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfiguredSet(@NotNull ValueManifest<Set<V>, V> manifest,
|
||||||
|
@NotNull Supplier<? extends Set<V>> constructor,
|
||||||
|
@NotNull ValueAdapter<V> paramAdapter) {
|
||||||
|
super(manifest, constructor, paramAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredSet<V> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>configured-parent</artifactId>
|
||||||
<version>4.0.7</version>
|
<version>4.2.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -16,13 +16,17 @@
|
|||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-feature-commentable</artifactId>
|
<artifactId>configured-feature-commentable</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Configured - Commentable Feature</name>
|
||||||
|
<url>https://github.com/CarmJos/configured</url>
|
||||||
|
<description>Enables comment support for configuration files in the Configured framework.</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
+15
-4
@@ -42,13 +42,24 @@ public interface CommentableMeta {
|
|||||||
|
|
||||||
static void register(@NotNull ConfigurationInitializer initializer) {
|
static void register(@NotNull ConfigurationInitializer initializer) {
|
||||||
initializer.registerAnnotation(
|
initializer.registerAnnotation(
|
||||||
HeaderComments.class, HEADER,
|
HeaderComments.class, HEADER,
|
||||||
a -> Arrays.asList(a.value())
|
a -> Arrays.asList(a.value())
|
||||||
);
|
);
|
||||||
initializer.registerAnnotation(
|
initializer.registerAnnotation(
|
||||||
FooterComments.class, FOOTER,
|
FooterComments.class, FOOTER,
|
||||||
a -> Arrays.asList(a.value())
|
a -> Arrays.asList(a.value())
|
||||||
);
|
);
|
||||||
|
initializer.registerAnnotation(InlineComment.class, INLINE, a -> {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
if (a.regex().length == 0) { // for current path
|
||||||
|
map.put(null, a.value());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
for (String regex : a.regex()) { // for specified path
|
||||||
|
map.put(regex, a.value());
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
});
|
||||||
initializer.registerAnnotation(InlineComments.class, INLINE, a -> {
|
initializer.registerAnnotation(InlineComments.class, INLINE, a -> {
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, String> map = new HashMap<>();
|
||||||
for (InlineComment comment : a.value()) {
|
for (InlineComment comment : a.value()) {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>configured-parent</artifactId>
|
||||||
<version>4.0.7</version>
|
<version>4.2.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -16,13 +16,17 @@
|
|||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-feature-file</artifactId>
|
<artifactId>configured-feature-file</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Configured - File Feature</name>
|
||||||
|
<url>https://github.com/CarmJos/configured</url>
|
||||||
|
<description>Provides file-based configuration support for the Configured framework.</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>configured-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@ import java.io.File;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public abstract class FileConfigFactory<SOURCE extends FileConfigSource<?, ?, SOURCE>,
|
public abstract class FileConfigFactory<SOURCE extends FileConfigSource<?, ?, SOURCE>,
|
||||||
HOLDER extends ConfigurationHolder<SOURCE>, SELF extends FileConfigFactory<SOURCE, HOLDER, SELF>>
|
HOLDER extends ConfigurationHolder<SOURCE>, SELF extends FileConfigFactory<SOURCE, HOLDER, SELF>>
|
||||||
extends ConfigurationFactory<SOURCE, HOLDER, SELF> {
|
extends ConfigurationFactory<SOURCE, HOLDER, SELF> {
|
||||||
|
|
||||||
|
|
||||||
protected @NotNull File file;
|
protected @NotNull File file;
|
||||||
|
|||||||
+2
-2
@@ -17,7 +17,7 @@ import java.nio.file.Files;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINAL, SELF extends FileConfigSource<SECTION, ORIGINAL, SELF>>
|
public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINAL, SELF extends FileConfigSource<SECTION, ORIGINAL, SELF>>
|
||||||
extends ConfigureSource<SECTION, ORIGINAL, SELF> {
|
extends ConfigureSource<SECTION, ORIGINAL, SELF> {
|
||||||
|
|
||||||
protected final @NotNull File file;
|
protected final @NotNull File file;
|
||||||
protected final @Nullable String resourcePath;
|
protected final @Nullable String resourcePath;
|
||||||
@@ -116,7 +116,7 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void saveResource(@NotNull String resourcePath, boolean replace)
|
protected void saveResource(@NotNull String resourcePath, boolean replace)
|
||||||
throws IOException, IllegalArgumentException {
|
throws IOException, IllegalArgumentException {
|
||||||
Objects.requireNonNull(resourcePath, "ResourcePath cannot be null");
|
Objects.requireNonNull(resourcePath, "ResourcePath cannot be null");
|
||||||
if (resourcePath.isEmpty()) throw new IllegalArgumentException("ResourcePath cannot be empty");
|
if (resourcePath.isEmpty()) throw new IllegalArgumentException("ResourcePath cannot be empty");
|
||||||
|
|
||||||
|
|||||||
-2
@@ -1,7 +1,5 @@
|
|||||||
package cc.carm.lib.configuration.source.option;
|
package cc.carm.lib.configuration.source.option;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user