Compare commits
170 Commits
1.0.0.M5-M
...
1.1.0.M2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91b818b8c1 | ||
|
|
7646a64770 | ||
|
|
94c057e89c | ||
|
|
190d7cefb0 | ||
|
|
669bc071b1 | ||
|
|
31b9b6b5c0 | ||
|
|
914ecd34fe | ||
|
|
74532ff199 | ||
|
|
c7bcb55bda | ||
|
|
afe560ca7d | ||
|
|
1380c49fd0 | ||
|
|
90240a8da5 | ||
|
|
ad587f63ed | ||
|
|
3c7cb592b3 | ||
|
|
5b15c9500a | ||
|
|
2d25f0d6e4 | ||
|
|
557fc869eb | ||
|
|
033f44e802 | ||
|
|
ee3c1bc007 | ||
|
|
f507fe2e4d | ||
|
|
4a27ba0a3f | ||
|
|
e2e5fd8b31 | ||
|
|
ba9abd1dd0 | ||
|
|
ab66614843 | ||
|
|
caa2f5f030 | ||
|
|
6e7c8f5771 | ||
|
|
44c4566c9d | ||
|
|
9a1e6226b1 | ||
|
|
cdb6d54d6a | ||
|
|
1fbfd3f0cb | ||
|
|
848e6f59c2 | ||
|
|
b3a891c69b | ||
|
|
54e105d19d | ||
|
|
4cfb62a413 | ||
|
|
7cdf9cedf3 | ||
|
|
fd198c172b | ||
|
|
4be229312c | ||
|
|
54ec7af462 | ||
|
|
7162677992 | ||
|
|
cf131aaa7e | ||
|
|
6cd3b7a3aa | ||
|
|
71e639402c | ||
|
|
fed31c74e1 | ||
|
|
5b13307e39 | ||
|
|
d317bcfa71 | ||
|
|
883bfbe79e | ||
|
|
7502ac137c | ||
|
|
3dfc59bfb8 | ||
|
|
9e50621c1b | ||
|
|
472beaf6d2 | ||
|
|
d6d8a13b0c | ||
|
|
3dcf93744b | ||
|
|
6373a70ca4 | ||
|
|
858afa80f1 | ||
|
|
97f57e3541 | ||
|
|
05c2045e45 | ||
|
|
d3598198a6 | ||
|
|
2a8fe5bac7 | ||
|
|
cdc8f52bad | ||
|
|
39492daa50 | ||
|
|
16904ba1a7 | ||
|
|
51a469b46f | ||
|
|
9f2b1f4ed0 | ||
|
|
e0ea8a6088 | ||
|
|
8861934336 | ||
|
|
93c9713adf | ||
|
|
68a0c1ee2c | ||
|
|
c3d533d59d | ||
|
|
e4b9be6b38 | ||
|
|
09a8b9c9c4 | ||
|
|
e531508bdc | ||
|
|
289c4b95ae | ||
|
|
25e6d6e025 | ||
|
|
83d18b5ce6 | ||
|
|
8f09748d78 | ||
|
|
4429971548 | ||
|
|
065a50bc8c | ||
|
|
f8daa69e53 | ||
|
|
8a18cd4aef | ||
|
|
3320208a1d | ||
|
|
4ebc6e96d3 | ||
|
|
91fe5480a8 | ||
|
|
b6322d7bbc | ||
|
|
572c4bb2cd | ||
|
|
9caa8b15cd | ||
|
|
275f4fe6b8 | ||
|
|
4c40ef7e3d | ||
|
|
609097c0dc | ||
|
|
307d86498e | ||
|
|
19879b8dab | ||
|
|
b190f22551 | ||
|
|
0e9c6a5de8 | ||
|
|
5ec0cc7327 | ||
|
|
817e167056 | ||
|
|
4a6fa5cade | ||
|
|
9cd33763b6 | ||
|
|
de8d2a1c74 | ||
|
|
9f940cd2b6 | ||
|
|
0d69baa32c | ||
|
|
433e5a660e | ||
|
|
ee33ce1571 | ||
|
|
9ac11e967a | ||
|
|
a89a0ac542 | ||
|
|
0ad0dad124 | ||
|
|
8f2771416e | ||
|
|
7af009cc7f | ||
|
|
35ad949c18 | ||
|
|
8206b5f950 | ||
|
|
170081137a | ||
|
|
6862bd8a45 | ||
|
|
490db7c39f | ||
|
|
f3979c3676 | ||
|
|
8d18729898 | ||
|
|
b5e0b2bec2 | ||
|
|
9eb47827c1 | ||
|
|
f97ab25411 | ||
|
|
6616761f50 | ||
|
|
89de566893 | ||
|
|
ea1f090b40 | ||
|
|
b5958fb5cc | ||
|
|
75b7aff80a | ||
|
|
7da0fcdd0c | ||
|
|
c88b6d89db | ||
|
|
de1540aadc | ||
|
|
d1b24d6cfb | ||
|
|
e85f3d3299 | ||
|
|
ef6e08d3f4 | ||
|
|
21010fbd49 | ||
|
|
4325d6c9fa | ||
|
|
bc16ccfded | ||
|
|
04f5f9f662 | ||
|
|
b1f1b8efaa | ||
|
|
de300e2643 | ||
|
|
20088b83d9 | ||
|
|
58f200f15e | ||
|
|
8718700249 | ||
|
|
f4063d1679 | ||
|
|
ef063613c7 | ||
|
|
2eda0f1701 | ||
|
|
ec7b65e21d | ||
|
|
c7f7571f3f | ||
|
|
9f71af42e8 | ||
|
|
92775170e1 | ||
|
|
4c7e338770 | ||
|
|
e3fff52d17 | ||
|
|
5477ab20b2 | ||
|
|
4cf3567f42 | ||
|
|
b26bb62a63 | ||
|
|
f156d7b5af | ||
|
|
7bf3643902 | ||
|
|
201ae3e92d | ||
|
|
07556ec58c | ||
|
|
39807b17e1 | ||
|
|
4913fe26ac | ||
|
|
7642a719ff | ||
|
|
6c1ce576a4 | ||
|
|
c99882201d | ||
|
|
ce6a64e4a9 | ||
|
|
2fcc323bcd | ||
|
|
17c7b1d2b5 | ||
|
|
cfefe46cd4 | ||
|
|
64921ddad1 | ||
|
|
edda1764fe | ||
|
|
8113b79109 | ||
|
|
9fde4dff3e | ||
|
|
d4b3e2b99d | ||
|
|
68a31d75f3 | ||
|
|
3e15c21419 | ||
|
|
e9f253d34f | ||
|
|
80aa057acb |
291
etc/formatting.xml
Normal file
291
etc/formatting.xml
Normal file
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Data" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
47
pom.xml
47
pom.xml
@@ -1,11 +1,10 @@
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongo-dist</artifactId>
|
||||
<artifactId>spring-data-mongodb-dist</artifactId>
|
||||
<name>Spring Data MongoDB Distribution</name>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.M2</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
@@ -145,37 +144,35 @@
|
||||
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
|
||||
<useExtensions>1</useExtensions>
|
||||
<highlightSource>1</highlightSource>
|
||||
<highlightDefaultLanguage></highlightDefaultLanguage>
|
||||
<highlightDefaultLanguage />
|
||||
<!-- callouts -->
|
||||
<entities>
|
||||
<entity>
|
||||
<name>version</name>
|
||||
<value>${pom.version}</value>
|
||||
<value>${project.version}</value>
|
||||
</entity>
|
||||
</entities>
|
||||
<postProcess>
|
||||
<copy todir="${project.basedir}/target/site/reference">
|
||||
<fileset dir="${project.basedir}/target/docbkx">
|
||||
<include name="**/*.html"/>
|
||||
<include name="**/*.pdf"/>
|
||||
<include name="**/*.html" />
|
||||
<include name="**/*.pdf" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${project.basedir}/target/site/reference/html">
|
||||
<fileset dir="${project.basedir}/src/docbkx/resources">
|
||||
<include name="**/*.css"/>
|
||||
<include name="**/*.png"/>
|
||||
<include name="**/*.gif"/>
|
||||
<include name="**/*.jpg"/>
|
||||
<include name="**/*.css" />
|
||||
<include name="**/*.png" />
|
||||
<include name="**/*.gif" />
|
||||
<include name="**/*.jpg" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${project.basedir}/target/site/reference/html">
|
||||
<fileset dir="${project.basedir}/src/docbkx/resources/images">
|
||||
<include name="*.png"/>
|
||||
<include name="*.png" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<move file="${project.basedir}/target/site/reference/pdf/index.pdf"
|
||||
tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf"
|
||||
failonerror="false"/>
|
||||
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf" failonerror="false" />
|
||||
</postProcess>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -184,7 +181,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<javadoc:aggregate>true</javadoc:aggregate>
|
||||
<aggregate>true</aggregate>
|
||||
<breakiterator>true</breakiterator>
|
||||
<header>Spring Data Document</header>
|
||||
<source>1.5</source>
|
||||
@@ -234,7 +231,7 @@
|
||||
<configuration>
|
||||
<tasks>
|
||||
<ant antfile="${basedir}/src/ant/upload-dist.xml">
|
||||
<target name="upload-dist"/>
|
||||
<target name="upload-dist" />
|
||||
</ant>
|
||||
</tasks>
|
||||
</configuration>
|
||||
@@ -263,16 +260,10 @@
|
||||
</build>
|
||||
|
||||
<pluginRepositories>
|
||||
<!-- Necessary for the build extension -->
|
||||
<pluginRepository>
|
||||
<!-- necessary for bundlor and utils -->
|
||||
<id>repository.plugin.springsource.release</id>
|
||||
<name>SpringSource Maven Repository</name>
|
||||
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>http://repo.springsource.org/plugins-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
@@ -282,7 +273,7 @@
|
||||
<site>
|
||||
<id>static.springframework.org</id>
|
||||
<url>
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/snapshot-site/
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
|
||||
</url>
|
||||
</site>
|
||||
<repository>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.M2</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
@@ -15,95 +15,34 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-core</artifactId>
|
||||
<version>${data.commons.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-aspects</artifactId>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.1.0.M2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -151,25 +90,7 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jboss-repository</id>
|
||||
<name>JBoss Public Repository</name>
|
||||
<url>http://repository.jboss.org/nexus/content/groups/public-jboss</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-milestones</id>
|
||||
<name>Springframework Maven Milestone Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-release</id>
|
||||
<name>Springframework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -58,10 +58,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
|
||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass,
|
||||
Object id, final ChangeSet changeSet)
|
||||
throws DataAccessException, NotFoundException {
|
||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
||||
throws DataAccessException, NotFoundException {
|
||||
|
||||
if (id == null) {
|
||||
log.debug("Unable to load MongoDB data for null id");
|
||||
@@ -77,8 +75,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
log.debug("Loading MongoDB data for " + dbk);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
for (DBObject dbo : collection.find(dbk)) {
|
||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -87,9 +84,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
if (!changeSet.getValues().containsKey(key)) {
|
||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||
if (className == null) {
|
||||
throw new DataIntegrityViolationException(
|
||||
"Unble to convert property " + key
|
||||
+ ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||
throw new DataIntegrityViolationException("Unble to convert property " + key + ": Invalid metadata, "
|
||||
+ ENTITY_FIELD_CLASS + " not available");
|
||||
}
|
||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||
@@ -135,10 +131,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||
DBObject dbId = mongoTemplate.execute(collName,
|
||||
new CollectionCallback<DBObject>() {
|
||||
public DBObject doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
|
||||
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
return collection.findOne(dbQuery);
|
||||
}
|
||||
});
|
||||
@@ -147,14 +141,12 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
log.debug("Flush: removing: " + dbQuery);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.remove(dbQuery);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
final DBObject dbDoc = new BasicDBObject();
|
||||
dbDoc.putAll(dbQuery);
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -166,8 +158,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
dbDoc.put("_id", dbId.get("_id"));
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.save(dbDoc);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -38,235 +38,234 @@ import org.springframework.data.crossstore.HashMapChangeSet;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Aspect to turn an object annotated with @Document into a persistent document
|
||||
* using Mongo.
|
||||
* Aspect to turn an object annotated with @Document into a persistent document using Mongo.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
public aspect MongoDocumentBacking {
|
||||
|
||||
private static final Log LOGGER = LogFactory
|
||||
.getLog(MongoDocumentBacking.class);
|
||||
private static final Log LOGGER = LogFactory.getLog(MongoDocumentBacking.class);
|
||||
|
||||
// Aspect shared config
|
||||
private ChangeSetPersister<Object> changeSetPersister;
|
||||
// Aspect shared config
|
||||
private ChangeSetPersister<Object> changeSetPersister;
|
||||
|
||||
public void setChangeSetPersister(
|
||||
ChangeSetPersister<Object> changeSetPersister) {
|
||||
this.changeSetPersister = changeSetPersister;
|
||||
}
|
||||
public void setChangeSetPersister(ChangeSetPersister<Object> changeSetPersister) {
|
||||
this.changeSetPersister = changeSetPersister;
|
||||
}
|
||||
|
||||
// ITD to introduce N state to Annotated objects
|
||||
declare parents : (@Entity *) implements DocumentBacked;
|
||||
// ITD to introduce N state to Annotated objects
|
||||
declare parents : (@Entity *) implements DocumentBacked;
|
||||
|
||||
// The annotated fields that will be persisted in MongoDB rather than with JPA
|
||||
declare @field: @RelatedDocument * (@Entity+ *).*:@Transient;
|
||||
// The annotated fields that will be persisted in MongoDB rather than with JPA
|
||||
declare @field: @RelatedDocument * (@Entity+ *).*:@Transient;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Advise user-defined constructors of ChangeSetBacked objects to create a new
|
||||
// backing ChangeSet
|
||||
// -------------------------------------------------------------------------
|
||||
pointcut arbitraryUserConstructorOfChangeSetBackedObject(DocumentBacked entity) :
|
||||
// -------------------------------------------------------------------------
|
||||
// Advise user-defined constructors of ChangeSetBacked objects to create a new
|
||||
// backing ChangeSet
|
||||
// -------------------------------------------------------------------------
|
||||
pointcut arbitraryUserConstructorOfChangeSetBackedObject(DocumentBacked entity) :
|
||||
execution((DocumentBacked+).new(..)) &&
|
||||
!execution((DocumentBacked+).new(ChangeSet)) &&
|
||||
this(entity);
|
||||
|
||||
pointcut finderConstructorOfChangeSetBackedObject(DocumentBacked entity,
|
||||
ChangeSet cs) :
|
||||
pointcut finderConstructorOfChangeSetBackedObject(DocumentBacked entity, ChangeSet cs) :
|
||||
execution((DocumentBacked+).new(ChangeSet)) &&
|
||||
this(entity) &&
|
||||
args(cs);
|
||||
|
||||
protected pointcut entityFieldGet(DocumentBacked entity) :
|
||||
protected pointcut entityFieldGet(DocumentBacked entity) :
|
||||
get(@RelatedDocument * DocumentBacked+.*) &&
|
||||
this(entity) &&
|
||||
!get(* DocumentBacked.*);
|
||||
|
||||
protected pointcut entityFieldSet(DocumentBacked entity, Object newVal) :
|
||||
protected pointcut entityFieldSet(DocumentBacked entity, Object newVal) :
|
||||
set(@RelatedDocument * DocumentBacked+.*) &&
|
||||
this(entity) &&
|
||||
args(newVal) &&
|
||||
!set(* DocumentBacked.*);
|
||||
|
||||
// intercept EntityManager.merge calls
|
||||
public pointcut entityManagerMerge(EntityManager em, Object entity) :
|
||||
// intercept EntityManager.merge calls
|
||||
public pointcut entityManagerMerge(EntityManager em, Object entity) :
|
||||
call(* EntityManager.merge(Object)) &&
|
||||
target(em) &&
|
||||
args(entity);
|
||||
|
||||
// intercept EntityManager.remove calls
|
||||
// public pointcut entityManagerRemove(EntityManager em, Object entity) :
|
||||
// call(* EntityManager.remove(Object)) &&
|
||||
// target(em) &&
|
||||
// args(entity);
|
||||
|
||||
// move changeSet from detached entity to the newly merged persistent object
|
||||
Object around(EntityManager em, Object entity) : entityManagerMerge(em, entity) {
|
||||
Object mergedEntity = proceed(em, entity);
|
||||
if (entity instanceof DocumentBacked && mergedEntity instanceof DocumentBacked) {
|
||||
((DocumentBacked)mergedEntity).changeSet = ((DocumentBacked)entity).getChangeSet();
|
||||
}
|
||||
return mergedEntity;
|
||||
}
|
||||
// intercept EntityManager.remove calls
|
||||
// public pointcut entityManagerRemove(EntityManager em, Object entity) :
|
||||
// call(* EntityManager.remove(Object)) &&
|
||||
// target(em) &&
|
||||
// args(entity);
|
||||
|
||||
// clear changeSet from removed entity
|
||||
// Object around(EntityManager em, Object entity) : entityManagerRemove(em, entity) {
|
||||
// if (entity instanceof DocumentBacked) {
|
||||
// removeChangeSetValues((DocumentBacked)entity);
|
||||
// }
|
||||
// return proceed(em, entity);
|
||||
// }
|
||||
|
||||
private static void removeChangeSetValues(DocumentBacked entity) {
|
||||
LOGGER.debug("Removing all change-set values for " + entity);
|
||||
ChangeSet nulledCs = new HashMapChangeSet();
|
||||
DocumentBacked documentEntity = (DocumentBacked) entity;
|
||||
@SuppressWarnings("unchecked")
|
||||
ChangeSetPersister<Object> changeSetPersister = (ChangeSetPersister<Object>)documentEntity.itdChangeSetPersister;
|
||||
try {
|
||||
changeSetPersister.getPersistentState(
|
||||
documentEntity.getClass(),
|
||||
documentEntity.get_persistent_id(),
|
||||
documentEntity.getChangeSet());
|
||||
}
|
||||
catch (DataAccessException e) {}
|
||||
catch (NotFoundException e) {}
|
||||
for (String key :entity.getChangeSet().getValues().keySet()) {
|
||||
nulledCs.set(key, null);
|
||||
// move changeSet from detached entity to the newly merged persistent object
|
||||
Object around(EntityManager em, Object entity) : entityManagerMerge(em, entity) {
|
||||
Object mergedEntity = proceed(em, entity);
|
||||
if (entity instanceof DocumentBacked && mergedEntity instanceof DocumentBacked) {
|
||||
((DocumentBacked) mergedEntity).changeSet = ((DocumentBacked) entity).getChangeSet();
|
||||
}
|
||||
return mergedEntity;
|
||||
}
|
||||
entity.setChangeSet(nulledCs);
|
||||
}
|
||||
|
||||
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
|
||||
LOGGER
|
||||
.debug("User-defined constructor called on DocumentBacked object of class "
|
||||
+ entity.getClass());
|
||||
// Populate all ITD fields
|
||||
entity.setChangeSet(new HashMapChangeSet());
|
||||
entity.itdChangeSetPersister = changeSetPersister;
|
||||
entity.itdTransactionSynchronization =
|
||||
new ChangeSetBackedTransactionSynchronization(changeSetPersister, entity);
|
||||
//registerTransactionSynchronization(entity);
|
||||
}
|
||||
// clear changeSet from removed entity
|
||||
// Object around(EntityManager em, Object entity) : entityManagerRemove(em, entity) {
|
||||
// if (entity instanceof DocumentBacked) {
|
||||
// removeChangeSetValues((DocumentBacked)entity);
|
||||
// }
|
||||
// return proceed(em, entity);
|
||||
// }
|
||||
|
||||
private static void registerTransactionSynchronization(DocumentBacked entity) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
if (!TransactionSynchronizationManager.getSynchronizations().contains(entity.itdTransactionSynchronization)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Adding transaction synchronization for " + entity);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(entity.itdTransactionSynchronization);
|
||||
}
|
||||
else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization already active for " + entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization is not active for " + entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void removeChangeSetValues(DocumentBacked entity) {
|
||||
LOGGER.debug("Removing all change-set values for " + entity);
|
||||
ChangeSet nulledCs = new HashMapChangeSet();
|
||||
DocumentBacked documentEntity = (DocumentBacked) entity;
|
||||
@SuppressWarnings("unchecked")
|
||||
ChangeSetPersister<Object> changeSetPersister = (ChangeSetPersister<Object>) documentEntity.itdChangeSetPersister;
|
||||
try {
|
||||
changeSetPersister.getPersistentState(documentEntity.getClass(), documentEntity.get_persistent_id(),
|
||||
documentEntity.getChangeSet());
|
||||
} catch (DataAccessException e) {
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
for (String key : entity.getChangeSet().getValues().keySet()) {
|
||||
nulledCs.set(key, null);
|
||||
}
|
||||
entity.setChangeSet(nulledCs);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ChangeSet-related mixins
|
||||
// -------------------------------------------------------------------------
|
||||
// Introduced field
|
||||
@Transient private ChangeSet DocumentBacked.changeSet;
|
||||
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
|
||||
LOGGER.debug("User-defined constructor called on DocumentBacked object of class " + entity.getClass());
|
||||
// Populate all ITD fields
|
||||
entity.setChangeSet(new HashMapChangeSet());
|
||||
entity.itdChangeSetPersister = changeSetPersister;
|
||||
entity.itdTransactionSynchronization = new ChangeSetBackedTransactionSynchronization(changeSetPersister, entity);
|
||||
// registerTransactionSynchronization(entity);
|
||||
}
|
||||
|
||||
@Transient private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
|
||||
private static void registerTransactionSynchronization(DocumentBacked entity) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
if (!TransactionSynchronizationManager.getSynchronizations().contains(entity.itdTransactionSynchronization)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Adding transaction synchronization for " + entity);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(entity.itdTransactionSynchronization);
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization already active for " + entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization is not active for " + entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transient private ChangeSetBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
|
||||
// -------------------------------------------------------------------------
|
||||
// ChangeSet-related mixins
|
||||
// -------------------------------------------------------------------------
|
||||
// Introduced field
|
||||
@Transient
|
||||
private ChangeSet DocumentBacked.changeSet;
|
||||
|
||||
public void DocumentBacked.setChangeSet(ChangeSet cs) {
|
||||
this.changeSet = cs;
|
||||
}
|
||||
@Transient
|
||||
private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
|
||||
|
||||
public ChangeSet DocumentBacked.getChangeSet() {
|
||||
return changeSet;
|
||||
}
|
||||
@Transient
|
||||
private ChangeSetBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
|
||||
|
||||
// Flush the entity state to the persistent store
|
||||
public void DocumentBacked.flush() {
|
||||
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
itdChangeSetPersister.persistState(this, this.changeSet);
|
||||
}
|
||||
public void DocumentBacked.setChangeSet(ChangeSet cs) {
|
||||
this.changeSet = cs;
|
||||
}
|
||||
|
||||
public Object DocumentBacked.get_persistent_id() {
|
||||
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
}
|
||||
public ChangeSet DocumentBacked.getChangeSet() {
|
||||
return changeSet;
|
||||
}
|
||||
|
||||
// lifecycle methods
|
||||
@javax.persistence.PostPersist public void DocumentBacked.itdPostPersist() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PrePersist: " + this.getClass().getName());
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
@javax.persistence.PreUpdate public void DocumentBacked.itdPreUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PreUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
@javax.persistence.PostUpdate public void DocumentBacked.itdPostUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
@javax.persistence.PostRemove public void DocumentBacked.itdPostRemove() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostRemove: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
removeChangeSetValues(this);
|
||||
}
|
||||
@javax.persistence.PostLoad public void DocumentBacked.itdPostLoad() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostLoad: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field reads to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity): entityFieldGet(entity) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("GET " + f + " -> ChangeSet value property [" + propName
|
||||
+ "] using: " + entity.getChangeSet());
|
||||
if (entity.getChangeSet().getValues().get(propName) == null) {
|
||||
try {
|
||||
this.changeSetPersister.getPersistentState(entity.getClass(),
|
||||
entity.get_persistent_id(), entity.getChangeSet());
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
}
|
||||
Object fValue = entity.getChangeSet().getValues().get(propName);
|
||||
if (fValue != null) {
|
||||
return fValue;
|
||||
}
|
||||
return proceed(entity);
|
||||
}
|
||||
// Flush the entity state to the persistent store
|
||||
public void DocumentBacked.flush() {
|
||||
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
itdChangeSetPersister.persistState(this, this.changeSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field writes to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity, Object newVal) : entityFieldSet(entity, newVal) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("SET " + f + " -> ChangeSet number value property [" + propName
|
||||
+ "] with value=[" + newVal + "]");
|
||||
entity.getChangeSet().set(propName, newVal);
|
||||
return proceed(entity, newVal);
|
||||
}
|
||||
public Object DocumentBacked.get_persistent_id() {
|
||||
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
}
|
||||
|
||||
Field field(JoinPoint joinPoint) {
|
||||
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
|
||||
return fieldSignature.getField();
|
||||
}
|
||||
// lifecycle methods
|
||||
@javax.persistence.PostPersist
|
||||
public void DocumentBacked.itdPostPersist() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PrePersist: " + this.getClass().getName());
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PreUpdate
|
||||
public void DocumentBacked.itdPreUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PreUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostUpdate
|
||||
public void DocumentBacked.itdPostUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostRemove
|
||||
public void DocumentBacked.itdPostRemove() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostRemove: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
removeChangeSetValues(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostLoad
|
||||
public void DocumentBacked.itdPostLoad() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostLoad: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field reads to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity): entityFieldGet(entity) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("GET " + f + " -> ChangeSet value property [" + propName + "] using: " + entity.getChangeSet());
|
||||
if (entity.getChangeSet().getValues().get(propName) == null) {
|
||||
try {
|
||||
this.changeSetPersister
|
||||
.getPersistentState(entity.getClass(), entity.get_persistent_id(), entity.getChangeSet());
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
}
|
||||
Object fValue = entity.getChangeSet().getValues().get(propName);
|
||||
if (fValue != null) {
|
||||
return fValue;
|
||||
}
|
||||
return proceed(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field writes to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity, Object newVal) : entityFieldSet(entity, newVal) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("SET " + f + " -> ChangeSet number value property [" + propName + "] with value=[" + newVal + "]");
|
||||
entity.getChangeSet().set(propName, newVal);
|
||||
return proceed(entity, newVal);
|
||||
}
|
||||
|
||||
Field field(JoinPoint joinPoint) {
|
||||
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
|
||||
return fieldSignature.getField();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ import java.lang.annotation.Target;
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({
|
||||
ElementType.FIELD
|
||||
})
|
||||
@Target({ ElementType.FIELD })
|
||||
public @interface RelatedDocument {
|
||||
}
|
||||
|
||||
@@ -90,8 +90,7 @@ public class CrossStoreMongoTests {
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
||||
found.setAge(44);
|
||||
}
|
||||
@@ -106,8 +105,7 @@ public class CrossStoreMongoTests {
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-" + "; "
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-" + "; "
|
||||
+ "SpringDeveloper.com, Consultant, 2005-2006", found.getResume().getJobs());
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ public class Address {
|
||||
private String state;
|
||||
private String zip;
|
||||
|
||||
public Address(Integer streetNumber, String streetName, String city,
|
||||
String state, String zip) {
|
||||
public Address(Integer streetNumber, String streetName, String city, String state, String zip) {
|
||||
super();
|
||||
this.streetNumber = streetNumber;
|
||||
this.streetName = streetName;
|
||||
@@ -36,34 +35,41 @@ public class Address {
|
||||
public Integer getStreetNumber() {
|
||||
return streetNumber;
|
||||
}
|
||||
|
||||
public void setStreetNumber(Integer streetNumber) {
|
||||
this.streetNumber = streetNumber;
|
||||
}
|
||||
|
||||
public String getStreetName() {
|
||||
return streetName;
|
||||
}
|
||||
|
||||
public void setStreetName(String streetName) {
|
||||
this.streetName = streetName;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getZip() {
|
||||
return zip;
|
||||
}
|
||||
|
||||
public void setZip(String zip) {
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ and connects directly to the MongoDB server using the driver. It has no dependen
|
||||
|
||||
To use it, configure a host, port, (optionally) applicationId, and database property in your Log4J configuration:
|
||||
|
||||
log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout=org.springframework.data.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
log4j.appender.stdout.host = localhost
|
||||
@@ -32,7 +32,7 @@ An example log entry might look like:
|
||||
{
|
||||
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
|
||||
"applicationId" : "my.application",
|
||||
"name" : "org.springframework.data.document.mongodb.log4j.AppenderTest",
|
||||
"name" : "org.springframework.data.mongodb.log4j.AppenderTest",
|
||||
"level" : "DEBUG",
|
||||
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
|
||||
"properties" : {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.M2</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||
@@ -28,45 +27,7 @@
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.log4j;
|
||||
package org.springframework.data.mongodb.log4j;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.log4j;
|
||||
package org.springframework.data.mongodb.log4j;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -1,6 +1,6 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout=org.springframework.data.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
log4j.appender.stdout.host = localhost
|
||||
|
||||
@@ -1,61 +1,28 @@
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<name>Spring Data MongoDB Parent</name>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.M2</version>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- versions for commonly-used dependencies -->
|
||||
<junit.version>4.8.1</junit.version>
|
||||
<log4j.version>1.2.15</log4j.version>
|
||||
<org.mockito.version>1.8.4</org.mockito.version>
|
||||
<org.slf4j.version>1.5.10</org.slf4j.version>
|
||||
<junit.version>4.10</junit.version>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
<org.mockito.version>1.9.0</org.mockito.version>
|
||||
<org.slf4j.version>1.6.1</org.slf4j.version>
|
||||
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
|
||||
<org.springframework.version>3.0.6.RELEASE</org.springframework.version>
|
||||
<data.commons.version>1.2.0.M2</data.commons.version>
|
||||
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
||||
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
|
||||
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
|
||||
<data.commons.version>1.4.0.M1</data.commons.version>
|
||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
||||
<bundlor.failOnWarnings>true</bundlor.failOnWarnings>
|
||||
</properties>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>strict</id>
|
||||
<properties>
|
||||
<maven.test.failure.ignore>false</maven.test.failure.ignore>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>fast</id>
|
||||
<properties>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>staging</id>
|
||||
<distributionManagement>
|
||||
<site>
|
||||
<id>spring-site-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/mongodb/docs</url>
|
||||
</site>
|
||||
<repository>
|
||||
<id>spring-milestone-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/mongodb/milestone</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>spring-snapshot-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/mongodb/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>bootstrap</id>
|
||||
<!-- TODO: move the repositories in here before release -->
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<distributionManagement>
|
||||
<!-- see 'staging' profile for dry-run deployment settings -->
|
||||
<downloadUrl>http://www.springsource.com/download/community
|
||||
@@ -63,7 +30,7 @@
|
||||
<site>
|
||||
<id>static.springframework.org</id>
|
||||
<url>
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/mongodb/docs/${project.version}
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
|
||||
</url>
|
||||
</site>
|
||||
<repository>
|
||||
@@ -77,163 +44,68 @@
|
||||
<url>s3://maven.springframework.org/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<dependencyManagement>
|
||||
<!--
|
||||
inheritable <dependency> declarations for child poms. children still
|
||||
must explicitly declare the groupId/artifactId of these dependencies
|
||||
in order for them to show up on the classpath, but metadata like
|
||||
<version> and <scope> are inherited, which cuts down on verbosity.
|
||||
see
|
||||
http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html
|
||||
-->
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-core</artifactId>
|
||||
<version>${data.commons.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-aspects</artifactId>
|
||||
<version>${data.commons.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-couchdb</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${org.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!--
|
||||
dependency definitions to be inherited by child poms. any
|
||||
<dependency> declarations here will automatically show up on child
|
||||
project classpaths. only items that are truly common across all
|
||||
projects (modules and samples) should go here. otherwise, consider
|
||||
<dependencyManagement> above
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${org.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -289,6 +161,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
@@ -308,19 +181,21 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.12</version>
|
||||
<configuration>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
<exclude>**/PerformanceTests.java</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
<junitArtifactName>junit:junit-dep</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
@@ -351,7 +226,7 @@
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
<version>1.0.0.RELEASE</version>
|
||||
<configuration>
|
||||
<failOnWarnings>true</failOnWarnings>
|
||||
<failOnWarnings>${bundlor.failOnWarnings}</failOnWarnings>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -367,32 +242,14 @@
|
||||
</build>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<!-- necessary for bundlor and utils -->
|
||||
<id>repository.plugin.springsource.release</id>
|
||||
<name>SpringSource Maven Repository</name>
|
||||
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>http://repo.springsource.org/plugins-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.milestone</id>
|
||||
<name>Spring Framework Maven Milestone Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.snapshot</id>
|
||||
<name>Spring Framework Maven Snapshot Repository</name>
|
||||
<url>http://maven.springframework.org/snapshot</url>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<reporting>
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
||||
</element>
|
||||
<element name="GridFS" type="Layer">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.gridfs.**" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
||||
</element>
|
||||
<element name="Core" type="Layer">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.core.**" type="IncludeTypePattern"/>
|
||||
|
||||
@@ -1,36 +1,56 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<?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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.M2</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
<properties>
|
||||
<mongo.version>2.6.5</mongo.version>
|
||||
<querydsl.version>2.2.4</querydsl.version>
|
||||
<mongo.version>2.7.1</mongo.version>
|
||||
<querydsl.version>2.6.0</querydsl.version>
|
||||
<cdi.version>1.0</cdi.version>
|
||||
<validation.version>1.0.0.GA</validation.version>
|
||||
<webbeans.version>1.1.3</webbeans.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
@@ -76,58 +96,81 @@
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- CDI -->
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi.version}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>el-api</artifactId>
|
||||
<version>${cdi.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JSR 303 Validation -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>4.2.0.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>performance-tests</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.8</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/PerformanceTests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>none</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit-dep</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -154,15 +197,5 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>querydsl</id>
|
||||
<name>Mysema QueryDsl</name>
|
||||
<url>http://source.mysema.com/maven2/releases</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,42 +16,51 @@
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
|
||||
/**
|
||||
* Exception being thrown in case we cannot connect to a MongoDB instance.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
|
||||
|
||||
private String username;
|
||||
|
||||
private char[] password;
|
||||
|
||||
private String database;
|
||||
private final UserCredentials credentials;
|
||||
private final String database;
|
||||
|
||||
private static final long serialVersionUID = 1172099106475265589L;
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
this.database = null;
|
||||
this.credentials = UserCredentials.NO_CREDENTIALS;
|
||||
}
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg) {
|
||||
super(msg);
|
||||
this(msg, null, UserCredentials.NO_CREDENTIALS);
|
||||
}
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg, String database, String username, char[] password) {
|
||||
public CannotGetMongoDbConnectionException(String msg, String database, UserCredentials credentials) {
|
||||
super(msg);
|
||||
this.username = username;
|
||||
this.password = password == null ? null : password.clone();
|
||||
this.database = database;
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public char[] getPassword() {
|
||||
return password;
|
||||
/**
|
||||
* Returns the {@link UserCredentials} that were used when trying to connect to the MongoDB instance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public UserCredentials getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the database trying to be accessed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,88 +15,176 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Base class for Spring Data Mongo configuration using JavaConfig.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractMongoConfiguration {
|
||||
|
||||
public abstract String getDatabaseName();
|
||||
/**
|
||||
* Return the name of the database to connect to.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
protected abstract String getDatabaseName();
|
||||
|
||||
/**
|
||||
* Return the {@link Mongo} instance to connect to.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public abstract Mongo mongo() throws Exception;
|
||||
|
||||
/**
|
||||
* Creates a {@link MongoTemplate}.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public MongoTemplate mongoTemplate() throws Exception {
|
||||
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link Mongo} instance
|
||||
* configured in {@link #mongo()}.
|
||||
*
|
||||
* @see #mongo()
|
||||
* @see #mongoTemplate()
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public MongoDbFactory mongoDbFactory() throws Exception {
|
||||
if (getUserCredentials() == null) {
|
||||
public SimpleMongoDbFactory mongoDbFactory() throws Exception {
|
||||
|
||||
UserCredentials credentials = getUserCredentials();
|
||||
|
||||
if (credentials == null) {
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
|
||||
} else {
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials());
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), credentials);
|
||||
}
|
||||
}
|
||||
|
||||
public String getMappingBasePackage() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public UserCredentials getUserCredentials() {
|
||||
/**
|
||||
* Return the base package to scan for mapped {@link Document}s.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String getMappingBasePackage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
|
||||
* be used.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected UserCredentials getUserCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
|
||||
*
|
||||
* @see #getMappingBasePackage()
|
||||
* @return
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@Bean
|
||||
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
|
||||
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
||||
mappingContext.initialize();
|
||||
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
||||
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
|
||||
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
@Bean
|
||||
public CustomConversions customConversions() {
|
||||
return new CustomConversions(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
|
||||
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
|
||||
*
|
||||
* @see #customConversions()
|
||||
* @see #mongoMappingContext()
|
||||
* @see #mongoDbFactory()
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
||||
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext());
|
||||
converter.setCustomConversions(customConversions());
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the mapping base package for classes annotated with {@link Document}.
|
||||
*
|
||||
* @see #getMappingBasePackage()
|
||||
* @return
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||
|
||||
String basePackage = getMappingBasePackage();
|
||||
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
|
||||
if (StringUtils.hasText(basePackage)) {
|
||||
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
|
||||
false);
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
|
||||
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), mappingContext.getClass()
|
||||
.getClassLoader()));
|
||||
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
|
||||
AbstractMongoConfiguration.class.getClassLoader()));
|
||||
}
|
||||
mappingContext.setInitialEntitySet(initialEntitySet);
|
||||
}
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingMongoConverter mappingMongoConverter() throws Exception {
|
||||
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext());
|
||||
afterMappingMongoConverterCreation(converter);
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that allows post-processing after the MappingMongoConverter has been successfully created.
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
|
||||
return initialEntitySet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,5 @@ public abstract class BeanNames {
|
||||
static final String INDEX_HELPER = "indexCreationHelper";
|
||||
static final String MONGO = "mongo";
|
||||
static final String DB_FACTORY = "mongoDbFactory";
|
||||
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,11 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -27,33 +29,49 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* Bean definition parser for the {@code mapping-converter} element.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Maciej Walkowiak
|
||||
*/
|
||||
public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final String BASE_PACKAGE = "base-package";
|
||||
private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator",
|
||||
MappingMongoConverterParser.class.getClassLoader());
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
@@ -97,9 +115,53 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
||||
|
||||
if (validatingMongoEventListener != null) {
|
||||
registry.registerBeanDefinition(VALIDATING_EVENT_LISTENER, validatingMongoEventListener);
|
||||
}
|
||||
|
||||
return converterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||
|
||||
String disableValidation = element.getAttribute("disable-validation");
|
||||
boolean validationDisabled = StringUtils.hasText(disableValidation) && Boolean.valueOf(disableValidation);
|
||||
|
||||
if (!validationDisabled) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
|
||||
RuntimeBeanReference validator = getValidator(builder, parserContext);
|
||||
|
||||
if (validator != null) {
|
||||
|
||||
builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class);
|
||||
builder.addConstructorArgValue(validator);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private RuntimeBeanReference getValidator(Object source, ParserContext parserContext) {
|
||||
|
||||
if (!jsr303Present) {
|
||||
return null;
|
||||
}
|
||||
|
||||
RootBeanDefinition validatorDef = new RootBeanDefinition(
|
||||
"org.springframework.validation.beanvalidation.LocalValidatorFactoryBean");
|
||||
validatorDef.setSource(source);
|
||||
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||
|
||||
return new RuntimeBeanReference(validatorName);
|
||||
}
|
||||
|
||||
private String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition) {
|
||||
|
||||
@@ -133,15 +195,29 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
||||
|
||||
if (customConvertersElements.size() == 1) {
|
||||
|
||||
Element customerConvertersElement = customConvertersElements.get(0);
|
||||
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<BeanMetadataElement>();
|
||||
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
||||
|
||||
if (converterElements != null) {
|
||||
for (Element listenerElement : converterElements) {
|
||||
converterBeans.add(parseConverter(listenerElement, parserContext));
|
||||
}
|
||||
}
|
||||
|
||||
// Scan for Converter and GenericConverter beans in the given base-package
|
||||
String packageToScan = customerConvertersElement.getAttribute(BASE_PACKAGE);
|
||||
if (StringUtils.hasText(packageToScan)) {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
|
||||
new AssignableTypeFilter(GenericConverter.class)));
|
||||
|
||||
for (BeanDefinition candidate : provider.findCandidateComponents(packageToScan)) {
|
||||
converterBeans.add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder conversionsBuilder = BeanDefinitionBuilder.rootBeanDefinition(CustomConversions.class);
|
||||
conversionsBuilder.addConstructorArgValue(converterBeans);
|
||||
|
||||
@@ -194,4 +270,39 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
"Element <converter> must specify 'ref' or contain a bean definition for the converter", element);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class NegatingFilter implements TypeFilter {
|
||||
|
||||
private final Set<TypeFilter> delegates;
|
||||
|
||||
/**
|
||||
* Creates a new {@link NegatingFilter} with the given delegates.
|
||||
*
|
||||
* @param filters
|
||||
*/
|
||||
public NegatingFilter(TypeFilter... filters) {
|
||||
Assert.notNull(filters);
|
||||
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.type.filter.TypeFilter#match(org.springframework.core.type.classreading.MetadataReader, org.springframework.core.type.classreading.MetadataReaderFactory)
|
||||
*/
|
||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
|
||||
|
||||
for (TypeFilter delegate : delegates) {
|
||||
if (delegate.match(metadataReader, metadataReaderFactory)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 by the original author(s).
|
||||
* Copyright 2011-2012 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,19 +15,19 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
||||
import static org.springframework.data.mongodb.config.ParsingUtils.*;
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -44,19 +44,29 @@ import com.mongodb.MongoURI;
|
||||
*/
|
||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
String id = element.getAttribute("id");
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = DB_FACTORY;
|
||||
}
|
||||
return id;
|
||||
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.DB_FACTORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
|
||||
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||
|
||||
String uri = element.getAttribute("uri");
|
||||
String mongoRef = element.getAttribute("mongo-ref");
|
||||
String dbname = element.getAttribute("dbname");
|
||||
@@ -64,29 +74,38 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
// Common setup
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
|
||||
|
||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||
|
||||
if (StringUtils.hasText(uri)) {
|
||||
if(StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", parserContext.extractSource(element));
|
||||
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", source);
|
||||
}
|
||||
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
|
||||
|
||||
// Defaulting
|
||||
mongoRef = StringUtils.hasText(mongoRef) ? mongoRef : registerMongoBeanDefinition(element, parserContext);
|
||||
if (StringUtils.hasText(mongoRef)) {
|
||||
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
||||
} else {
|
||||
dbFactoryBuilder.addConstructorArgValue(registerMongoBeanDefinition(element, parserContext));
|
||||
}
|
||||
|
||||
dbname = StringUtils.hasText(dbname) ? dbname : "db";
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef));
|
||||
dbFactoryBuilder.addConstructorArgValue(dbname);
|
||||
|
||||
if (userCredentials != null) {
|
||||
dbFactoryBuilder.addConstructorArgValue(userCredentials);
|
||||
}
|
||||
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
BeanDefinitionBuilder writeConcernPropertyEditorBuilder = getWriteConcernPropertyEditorBuilder();
|
||||
|
||||
BeanComponentDefinition component = helper.getComponent(writeConcernPropertyEditorBuilder);
|
||||
parserContext.registerBeanComponent(component);
|
||||
|
||||
return (AbstractBeanDefinition) helper.getComponentIdButFallback(dbFactoryBuilder, BeanNames.DB_FACTORY)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,14 +116,13 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
* @param parserContext must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
||||
private BeanDefinition registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
||||
|
||||
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||
ParsingUtils.setPropertyValue(element, mongoBuilder, "host");
|
||||
ParsingUtils.setPropertyValue(element, mongoBuilder, "port");
|
||||
setPropertyValue(mongoBuilder, element, "host");
|
||||
setPropertyValue(mongoBuilder, element, "port");
|
||||
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(mongoBuilder.getBeanDefinition(),
|
||||
parserContext.getRegistry());
|
||||
return getSourceBeanDefinition(mongoBuilder, parserContext, element);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +146,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
return getSourceBeanDefinition(userCredentialsBuilder, context, element);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI}.
|
||||
*
|
||||
@@ -136,10 +154,10 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinition getMongoUri(String uri) {
|
||||
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoURI.class);
|
||||
builder.addConstructorArgValue(uri);
|
||||
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigParser;
|
||||
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
|
||||
@@ -32,7 +34,10 @@ public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
||||
*/
|
||||
public void init() {
|
||||
|
||||
registerBeanDefinitionParser("repositories", new MongoRepositoryConfigParser());
|
||||
RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension();
|
||||
RepositoryBeanDefinitionParser repositoryBeanDefinitionParser = new RepositoryBeanDefinitionParser(extension);
|
||||
|
||||
registerBeanDefinitionParser("repositories", repositoryBeanDefinitionParser);
|
||||
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
||||
registerBeanDefinitionParser("mongo", new MongoParser());
|
||||
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,50 +13,81 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <mongo;gt; definitions. If no name
|
||||
* Parser for <mongo;gt; definitions.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParser extends AbstractSingleBeanDefinitionParser {
|
||||
public class MongoParser implements BeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return MongoFactoryBean.class;
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
Object source = parserContext.extractSource(element);
|
||||
String id = element.getAttribute("id");
|
||||
|
||||
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||
ParsingUtils.setPropertyValue(builder, element, "port", "port");
|
||||
ParsingUtils.setPropertyValue(builder, element, "host", "host");
|
||||
ParsingUtils.setPropertyValue(builder, element, "write-concern", "writeConcern");
|
||||
|
||||
MongoParsingUtils.parseMongoOptions(element, builder);
|
||||
MongoParsingUtils.parseReplicaSet(element, builder);
|
||||
|
||||
String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO;
|
||||
|
||||
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mongo", source));
|
||||
|
||||
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
||||
parserContext.registerBeanComponent(mongoComponent);
|
||||
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(registerServerAddressPropertyEditor());
|
||||
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
||||
BeanComponentDefinition writeConcernPropertyEditor = helper.getComponent(MongoParsingUtils
|
||||
.getWriteConcernPropertyEditorBuilder());
|
||||
parserContext.registerBeanComponent(writeConcernPropertyEditor);
|
||||
|
||||
parserContext.popAndRegisterContainingComponent();
|
||||
|
||||
return mongoComponent.getBeanDefinition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
super.doParse(element, builder);
|
||||
/**
|
||||
* One should only register one bean definition but want to have the convenience of using
|
||||
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
||||
* container.
|
||||
*/
|
||||
private BeanDefinitionBuilder registerServerAddressPropertyEditor() {
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, "port", "port");
|
||||
ParsingUtils.setPropertyValue(element, builder, "host", "host");
|
||||
ParsingUtils.setPropertyValue(element, builder, "write-concern", "writeConcern");
|
||||
|
||||
ParsingUtils.parseMongoOptions(parserContext, element, builder);
|
||||
ParsingUtils.parseReplicaSet(parserContext, element, builder);
|
||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||
customEditors.put("com.mongodb.ServerAddress[]",
|
||||
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||
builder.addPropertyValue("customEditors", customEditors);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
String name = super.resolveId(element, definition, parserContext);
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = "mongo";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
abstract class MongoParsingUtils {
|
||||
|
||||
private MongoParsingUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the mongo replica-set element.
|
||||
*
|
||||
* @param parserContext the parser context
|
||||
* @param element the mongo element
|
||||
* @param mongoBuilder the bean definition builder to populate
|
||||
* @return
|
||||
*/
|
||||
static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the mongo:options sub-element. Populates the given attribute factory with the proper attributes.
|
||||
*
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||
if (optionsElement == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoOptionsFactoryBean.class);
|
||||
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
||||
"threadsAllowedToBlockForConnectionMultiplier");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "auto-connect-retry", "autoConnectRetry");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "write-number", "writeNumber");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
|
||||
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
|
||||
|
||||
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||
* {@link WriteConcernPropertyEditor}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
||||
|
||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
||||
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.class);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||
builder.addPropertyValue("customEditors", customEditors);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
abstract class ParsingUtils {
|
||||
|
||||
/**
|
||||
* Parses the mongo replica-set element.
|
||||
*
|
||||
* @param parserContext the parser context
|
||||
* @param element the mongo element
|
||||
* @param mongoBuilder the bean definition builder to populate
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseReplicaSet(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
|
||||
String replicaSetString = element.getAttribute("replica-set");
|
||||
if (StringUtils.hasText(replicaSetString)) {
|
||||
ManagedList<Object> serverAddresses = new ManagedList<Object>();
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
for (String element2 : replicaSetStringArray) {
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(element2, ":");
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(ServerAddress.class);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[0]);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[1]);
|
||||
serverAddresses.add(defBuilder.getBeanDefinition());
|
||||
}
|
||||
if (!serverAddresses.isEmpty()) {
|
||||
mongoBuilder.addPropertyValue("replicaSetSeeds", serverAddresses);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the mongo:options sub-element. Populates the given attribute factory with the proper attributes.
|
||||
*
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseMongoOptions(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||
if (optionsElement == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoOptionsFactoryBean.class);
|
||||
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "connections-per-host", "connectionsPerHost");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "threads-allowed-to-block-for-connection-multiplier",
|
||||
"threadsAllowedToBlockForConnectionMultiplier");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "max-wait-time", "maxWaitTime");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "connect-timeout", "connectTimeout");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "socket-timeout", "socketTimeout");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "socket-keep-alive", "socketKeepAlive");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "auto-connect-retry", "autoConnectRetry");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-number", "writeNumber");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-timeout", "writeTimeout");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-fsync", "writeFsync");
|
||||
setPropertyValue(optionsElement, optionsDefBuilder, "slave-ok", "slaveOk");
|
||||
|
||||
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName, String propertyName) {
|
||||
String attr = element.getAttribute(attrName);
|
||||
if (StringUtils.hasText(attr)) {
|
||||
builder.addPropertyValue(propertyName, attr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property with the given attribute name on the given {@link BeanDefinitionBuilder} to the value of the
|
||||
* attribute with the given name.
|
||||
*
|
||||
* @param element must not be {@literal null}.
|
||||
* @param builder must not be {@literal null}.
|
||||
* @param attrName must not be {@literal null} or empty.
|
||||
*/
|
||||
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName) {
|
||||
String attr = element.getAttribute(attrName);
|
||||
if (StringUtils.hasText(attr)) {
|
||||
builder.addPropertyValue(attrName, attr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder} enriched with source
|
||||
* information derived from the given {@link Element}.
|
||||
*
|
||||
* @param builder must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, ParserContext context, Element element) {
|
||||
AbstractBeanDefinition definition = builder.getBeanDefinition();
|
||||
definition.setSource(context.extractSource(element));
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* Parse a {@link String} to a {@link ServerAddress} array. The format is host1:port1,host2:port2,host3:port3.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ServerAddressPropertyEditor.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setAsText(String replicaSetString) {
|
||||
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
Set<ServerAddress> serverAddresses = new HashSet<ServerAddress>(replicaSetStringArray.length);
|
||||
|
||||
for (String element : replicaSetStringArray) {
|
||||
|
||||
ServerAddress address = parseServerAddress(element);
|
||||
|
||||
if (address != null) {
|
||||
serverAddresses.add(address);
|
||||
}
|
||||
}
|
||||
|
||||
if (serverAddresses.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not resolve at least one server of the replica set configuration! Validate your config!");
|
||||
}
|
||||
|
||||
setValue(serverAddresses.toArray(new ServerAddress[serverAddresses.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given source into a {@link ServerAddress}.
|
||||
*
|
||||
* @param source
|
||||
* @return the
|
||||
*/
|
||||
private ServerAddress parseServerAddress(String source) {
|
||||
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(source.trim(), ":");
|
||||
|
||||
if (!StringUtils.hasText(source) || hostAndPort.length > 2) {
|
||||
LOG.warn("Could not parse address source '{}'. Check your replica set configuration!", source);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return hostAndPort.length == 1 ? new ServerAddress(hostAndPort[0]) : new ServerAddress(hostAndPort[0],
|
||||
Integer.parseInt(hostAndPort[1]));
|
||||
} catch (UnknownHostException e) {
|
||||
LOG.warn("Could not parse host '{}'. Check your replica set configuration!", hostAndPort[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.warn("Could not parse port '{}'. Check your replica set configuration!", hostAndPort[1]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Converter to create {@link WriteConcern} instances from String representations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class StringToWriteConcernConverter implements Converter<String, WriteConcern> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
public WriteConcern convert(String source) {
|
||||
|
||||
WriteConcern writeConcern = WriteConcern.valueOf(source);
|
||||
return writeConcern != null ? writeConcern : new WriteConcern(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Parse a string to a {@link WriteConcern}. If it is a well know {@link String} as identified by the
|
||||
* {@link WriteConcern#valueOf(String)}, use the well known {@link WriteConcern} value, otherwise pass the string as is
|
||||
* to the constructor of the write concern. There is no support for other constructor signatures when parsing from a
|
||||
* string value.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class WriteConcernPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
/**
|
||||
* Parse a string to a List<ServerAddress>
|
||||
*/
|
||||
@Override
|
||||
public void setAsText(String writeConcernString) {
|
||||
|
||||
WriteConcern writeConcern = WriteConcern.valueOf(writeConcernString);
|
||||
if (writeConcern != null) {
|
||||
// have a well known string
|
||||
setValue(writeConcern);
|
||||
} else {
|
||||
// pass on the string to the constructor
|
||||
setValue(new WriteConcern(writeConcernString));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import com.mongodb.DBCursor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface CursorPreparer {
|
||||
interface CursorPreparer {
|
||||
|
||||
/**
|
||||
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.IndexField;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link IndexOperations}.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultIndexOperations implements IndexOperations {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultIndexOperations}.
|
||||
*
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param collectionName must not be {@literal null}.
|
||||
*/
|
||||
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName) {
|
||||
|
||||
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
|
||||
Assert.notNull(collectionName, "Collection name can not be null!");
|
||||
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)
|
||||
*/
|
||||
public void ensureIndex(final IndexDefinition indexDefinition) {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
DBObject indexOptions = indexDefinition.getIndexOptions();
|
||||
if (indexOptions != null) {
|
||||
collection.ensureIndex(indexDefinition.getIndexKeys(), indexOptions);
|
||||
} else {
|
||||
collection.ensureIndex(indexDefinition.getIndexKeys());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#dropIndex(java.lang.String)
|
||||
*/
|
||||
public void dropIndex(final String name) {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.dropIndex(name);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#dropAllIndexes()
|
||||
*/
|
||||
public void dropAllIndexes() {
|
||||
dropIndex("*");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#resetIndexCache()
|
||||
*/
|
||||
public void resetIndexCache() {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.resetIndexCache();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#getIndexInfo()
|
||||
*/
|
||||
public List<IndexInfo> getIndexInfo() {
|
||||
|
||||
return mongoOperations.execute(collectionName, new CollectionCallback<List<IndexInfo>>() {
|
||||
public List<IndexInfo> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
List<DBObject> dbObjectList = collection.getIndexInfo();
|
||||
return getIndexData(dbObjectList);
|
||||
}
|
||||
|
||||
private List<IndexInfo> getIndexData(List<DBObject> dbObjectList) {
|
||||
|
||||
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
|
||||
|
||||
for (DBObject ix : dbObjectList) {
|
||||
|
||||
DBObject keyDbObject = (DBObject) ix.get("key");
|
||||
int numberOfElements = keyDbObject.keySet().size();
|
||||
|
||||
List<IndexField> indexFields = new ArrayList<IndexField>(numberOfElements);
|
||||
|
||||
for (String key : keyDbObject.keySet()) {
|
||||
|
||||
Object value = keyDbObject.get(key);
|
||||
|
||||
if (Integer.valueOf(1).equals(value)) {
|
||||
indexFields.add(IndexField.create(key, Order.ASCENDING));
|
||||
} else if (Integer.valueOf(-1).equals(value)) {
|
||||
indexFields.add(IndexField.create(key, Order.DESCENDING));
|
||||
} else if ("2d".equals(value)) {
|
||||
indexFields.add(IndexField.geo(key));
|
||||
}
|
||||
}
|
||||
|
||||
String name = ix.get("name").toString();
|
||||
|
||||
boolean unique = ix.containsField("unique") ? (Boolean) ix.get("unique") : false;
|
||||
boolean dropDuplicates = ix.containsField("dropDups") ? (Boolean) ix.get("dropDups") : false;
|
||||
boolean sparse = ix.containsField("sparse") ? (Boolean) ix.get("sparse") : false;
|
||||
|
||||
indexInfoList.add(new IndexInfo(indexFields, name, unique, dropDuplicates, sparse));
|
||||
}
|
||||
|
||||
return indexInfoList;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -21,15 +21,16 @@ import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document basis.
|
||||
* Implementations of this interface perform the actual work of prcoessing each document but don't need to worry about
|
||||
* exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate
|
||||
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
|
||||
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
|
||||
* about exception handling. {@MongoException}s will be caught and translated by the calling
|
||||
* MongoTemplate
|
||||
*
|
||||
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for later
|
||||
* inspection.
|
||||
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later
|
||||
* for later inspection.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface DocumentCallbackHandler {
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
public class FindAndModifyOptions {
|
||||
|
||||
boolean returnNew;
|
||||
|
||||
boolean upsert;
|
||||
|
||||
boolean remove;
|
||||
|
||||
/**
|
||||
* Static factory method to create a FindAndModifyOptions instance
|
||||
*
|
||||
* @return a new instance
|
||||
*/
|
||||
public static FindAndModifyOptions options() {
|
||||
return new FindAndModifyOptions();
|
||||
}
|
||||
|
||||
public FindAndModifyOptions returnNew(boolean returnNew) {
|
||||
this.returnNew = returnNew;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FindAndModifyOptions upsert(boolean upsert) {
|
||||
this.upsert = upsert;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FindAndModifyOptions remove(boolean remove) {
|
||||
this.remove = remove;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isReturnNew() {
|
||||
return returnNew;
|
||||
}
|
||||
|
||||
public boolean isUpsert() {
|
||||
return upsert;
|
||||
}
|
||||
|
||||
public boolean isRemove() {
|
||||
return remove;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Index operations on a collection.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface IndexOperations {
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
|
||||
* class. If not it will be created.
|
||||
*
|
||||
* @param indexDefinition must not be {@literal null}.
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition);
|
||||
|
||||
/**
|
||||
* Drops an index from this collection.
|
||||
*
|
||||
* @param name name of index to drop
|
||||
*/
|
||||
void dropIndex(String name);
|
||||
|
||||
/**
|
||||
* Drops all indices from this collection.
|
||||
*/
|
||||
void dropAllIndexes();
|
||||
|
||||
/**
|
||||
* Clears all indices that have not yet been applied to this collection.
|
||||
*/
|
||||
void resetIndexCache();
|
||||
|
||||
/**
|
||||
* Returns the index information on the collection.
|
||||
*
|
||||
* @return index information on the collection
|
||||
*/
|
||||
List<IndexInfo> getIndexInfo();
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
||||
* WriteConcern based on this information.
|
||||
*
|
||||
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
|
||||
* the MongoActionOperaton.INSERT_LIST.
|
||||
*
|
||||
* <ul>
|
||||
* <li>INSERT, SAVE have null query</li>
|
||||
* <li>REMOVE has null document</li>
|
||||
* <li>INSERT_LIST has null entityClass, document, and query</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public class MongoAction {
|
||||
|
||||
private String collectionName;
|
||||
|
||||
private WriteConcern defaultWriteConcern;
|
||||
|
||||
private Class<?> entityClass;
|
||||
|
||||
private MongoActionOperation mongoActionOperation;
|
||||
|
||||
private DBObject query;
|
||||
|
||||
private DBObject document;
|
||||
|
||||
/**
|
||||
* Create an instance of a MongoAction
|
||||
*
|
||||
* @param defaultWriteConcern the default write concern
|
||||
* @param mongoActionOperation action being taken against the collection
|
||||
* @param collectionName the collection name
|
||||
* @param entityClass the POJO that is being operated against
|
||||
* @param document the converted DBObject from the POJO or Spring Update object
|
||||
* @param query the converted DBOjbect from the Spring Query object
|
||||
*/
|
||||
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
||||
String collectionName, Class<?> entityClass, DBObject document, DBObject query) {
|
||||
super();
|
||||
this.defaultWriteConcern = defaultWriteConcern;
|
||||
this.mongoActionOperation = mongoActionOperation;
|
||||
this.collectionName = collectionName;
|
||||
this.entityClass = entityClass;
|
||||
this.query = query;
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
|
||||
public WriteConcern getDefaultWriteConcern() {
|
||||
return defaultWriteConcern;
|
||||
}
|
||||
|
||||
public Class<?> getEntityClass() {
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
public MongoActionOperation getMongoActionOperation() {
|
||||
return mongoActionOperation;
|
||||
}
|
||||
|
||||
public DBObject getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public DBObject getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,21 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
/**
|
||||
* Interfaces for components being able to provide a {@link TypeMapper}.
|
||||
* Enumeration for operations on a collection. Used with {@link MongoAction} to help determine the WriteConcern to use
|
||||
* for a given mutating operation
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @see MongoAction
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface TypeKeyAware {
|
||||
public enum MongoActionOperation {
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeMapper}.
|
||||
*
|
||||
* @return the {@link TypeMapper} or {@literal null} if none available.
|
||||
*/
|
||||
boolean isTypeKey(String key);
|
||||
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,32 +15,28 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Mongo server administration exposed via JMX annotations
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
|
||||
@ManagedResource(description = "Mongo Admin Operations")
|
||||
public class MongoAdmin implements MongoAdminOperations {
|
||||
|
||||
/**
|
||||
* Logger available to subclasses
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Mongo mongo;
|
||||
private final Mongo mongo;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public MongoAdmin(Mongo mongo) {
|
||||
Assert.notNull(mongo);
|
||||
this.mongo = mongo;
|
||||
}
|
||||
|
||||
@@ -83,11 +79,10 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
* @param password The password to use
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
DB getDB(String databaseName) {
|
||||
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
|
||||
return MongoDbUtils.getDB(mongo, databaseName, new UserCredentials(username, password));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for internal MongoDb classes.
|
||||
* <p/>
|
||||
@@ -36,7 +38,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class MongoDbUtils {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDbUtils.class);
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
@@ -48,74 +50,90 @@ public abstract class MongoDbUtils {
|
||||
/**
|
||||
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
|
||||
*
|
||||
* @param mongo The {@link Mongo} instance
|
||||
* @param databaseName The database name
|
||||
* @return The {@link DB} connection
|
||||
* @param mongo the {@link Mongo} instance, must not be {@literal null}.
|
||||
* @param databaseName the database name, must not be {@literal null} or empty.
|
||||
* @return the {@link DB} connection
|
||||
*/
|
||||
public static DB getDB(Mongo mongo, String databaseName) {
|
||||
return doGetDB(mongo, databaseName, null, null, true);
|
||||
return doGetDB(mongo, databaseName, UserCredentials.NO_CREDENTIALS, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
|
||||
*
|
||||
* @param mongo The {@link Mongo} instance
|
||||
* @param databaseName The database name
|
||||
* @param username The username to authenticate with
|
||||
* @param password The password to authenticate with
|
||||
* @return The {@link DB} connection
|
||||
* @param mongo the {@link Mongo} instance, must not be {@literal null}.
|
||||
* @param databaseName the database name, must not be {@literal null} or empty.
|
||||
* @param credentials the credentials to use, must not be {@literal null}.
|
||||
* @return the {@link DB} connection
|
||||
*/
|
||||
public static DB getDB(Mongo mongo, String databaseName, String username, char[] password) {
|
||||
return doGetDB(mongo, databaseName, username, password, true);
|
||||
public static DB getDB(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||
|
||||
Assert.notNull(mongo, "No Mongo instance specified!");
|
||||
Assert.hasText(databaseName, "Database name must be given!");
|
||||
Assert.notNull(credentials, "Credentials must not be null, use UserCredentials.NO_CREDENTIALS!");
|
||||
|
||||
return doGetDB(mongo, databaseName, credentials, true);
|
||||
}
|
||||
|
||||
public static DB doGetDB(Mongo mongo, String databaseName, String username, char[] password, boolean allowCreate) {
|
||||
Assert.notNull(mongo, "No Mongo instance specified");
|
||||
private static DB doGetDB(Mongo mongo, String databaseName, UserCredentials credentials, boolean allowCreate) {
|
||||
|
||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||
|
||||
if (dbHolder != null && !dbHolder.isEmpty()) {
|
||||
// pre-bound Mongo DB
|
||||
|
||||
DB db = null;
|
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive() && dbHolder.doesNotHoldNonDefaultDB()) {
|
||||
// Spring transaction management is active ->
|
||||
db = dbHolder.getDB();
|
||||
|
||||
db = dbHolder.getDB(databaseName);
|
||||
|
||||
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
||||
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
|
||||
|
||||
LOGGER.debug("Registering Spring transaction synchronization for existing MongoDB {}.", databaseName);
|
||||
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
||||
dbHolder.setSynchronizedWithTransaction(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (db != null) {
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.trace("Getting Mongo Database name=[" + databaseName + "]");
|
||||
DB db = mongo.getDB(databaseName);
|
||||
LOGGER.debug("Getting Mongo Database name=[{}]", databaseName);
|
||||
|
||||
DB db = mongo.getDB(databaseName);
|
||||
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
||||
|
||||
boolean credentialsGiven = username != null && password != null;
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
// Note, can only authenticate once against the same com.mongodb.DB object.
|
||||
if (!db.authenticate(username, password)) {
|
||||
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||
|
||||
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [" + new String(password) + "]", databaseName, username,
|
||||
password);
|
||||
+ "], username = [" + username + "], password = [" + password + "]", databaseName, credentials);
|
||||
}
|
||||
}
|
||||
|
||||
// Use same Session for further Mongo actions within the transaction.
|
||||
// Thread object will get removed by synchronization at transaction completion.
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
|
||||
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
|
||||
|
||||
LOGGER.debug("Registering Spring transaction synchronization for MongoDB instance {}.", databaseName);
|
||||
|
||||
DbHolder holderToUse = dbHolder;
|
||||
|
||||
if (holderToUse == null) {
|
||||
holderToUse = new DbHolder(db);
|
||||
holderToUse = new DbHolder(databaseName, db);
|
||||
} else {
|
||||
holderToUse.addDB(db);
|
||||
holderToUse.addDB(databaseName, db);
|
||||
}
|
||||
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
|
||||
holderToUse.setSynchronizedWithTransaction(true);
|
||||
|
||||
if (holderToUse != dbHolder) {
|
||||
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
|
||||
}
|
||||
@@ -139,6 +157,7 @@ public abstract class MongoDbUtils {
|
||||
* @return whether the DB is transactional
|
||||
*/
|
||||
public static boolean isDBTransactional(DB db, Mongo mongo) {
|
||||
|
||||
if (mongo == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -152,6 +171,7 @@ public abstract class MongoDbUtils {
|
||||
* @param db the DB to close (may be <code>null</code>)
|
||||
*/
|
||||
public static void closeDB(DB db) {
|
||||
|
||||
if (db != null) {
|
||||
LOGGER.debug("Closing Mongo DB object");
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,17 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoOptions;
|
||||
import com.mongodb.ServerAddress;
|
||||
@@ -37,12 +38,10 @@ import com.mongodb.WriteConcern;
|
||||
* @author Oliver Gierke
|
||||
* @since 1.0
|
||||
*/
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptionTranslator {
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
|
||||
PersistenceExceptionTranslator {
|
||||
|
||||
/**
|
||||
* Logger, available to subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private Mongo mongo;
|
||||
|
||||
private MongoOptions mongoOptions;
|
||||
private String host;
|
||||
@@ -57,12 +56,12 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
this.mongoOptions = mongoOptions;
|
||||
}
|
||||
|
||||
public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) {
|
||||
this.replicaSetSeeds = replicaSetSeeds;
|
||||
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
|
||||
this.replicaSetSeeds = Arrays.asList(replicaSetSeeds);
|
||||
}
|
||||
|
||||
public void setReplicaPair(List<ServerAddress> replicaPair) {
|
||||
this.replicaPair = replicaPair;
|
||||
public void setReplicaPair(ServerAddress[] replicaPair) {
|
||||
this.replicaPair = Arrays.asList(replicaPair);
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
@@ -87,34 +86,7 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
}
|
||||
|
||||
public Mongo getObject() throws Exception {
|
||||
|
||||
Mongo mongo;
|
||||
|
||||
ServerAddress defaultOptions = new ServerAddress();
|
||||
|
||||
if (mongoOptions == null) {
|
||||
mongoOptions = new MongoOptions();
|
||||
}
|
||||
|
||||
if (replicaPair != null) {
|
||||
if (replicaPair.size() < 2) {
|
||||
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
||||
}
|
||||
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
||||
} else if (replicaSetSeeds != null) {
|
||||
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
||||
} else {
|
||||
String mongoHost = host != null ? host : defaultOptions.getHost();
|
||||
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
||||
mongoOptions);
|
||||
}
|
||||
|
||||
if (writeConcern != null) {
|
||||
mongo.setWriteConcern(writeConcern);
|
||||
}
|
||||
|
||||
return mongo;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -140,4 +112,45 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
Mongo mongo;
|
||||
ServerAddress defaultOptions = new ServerAddress();
|
||||
|
||||
if (mongoOptions == null) {
|
||||
mongoOptions = new MongoOptions();
|
||||
}
|
||||
|
||||
if (replicaPair != null) {
|
||||
if (replicaPair.size() < 2) {
|
||||
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
||||
}
|
||||
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
||||
} else if (replicaSetSeeds != null) {
|
||||
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
||||
} else {
|
||||
String mongoHost = host != null ? host : defaultOptions.getHost();
|
||||
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
||||
mongoOptions);
|
||||
}
|
||||
|
||||
if (writeConcern != null) {
|
||||
mongo.setWriteConcern(writeConcern);
|
||||
}
|
||||
|
||||
this.mongo = mongo;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
this.mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,24 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.mapreduce.GroupBy;
|
||||
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
import com.mongodb.CommandResult;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteResult;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
|
||||
* a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK
|
||||
@@ -48,6 +51,7 @@ public interface MongoOperations {
|
||||
/**
|
||||
* The collection name used for the specified class by this template.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
@@ -68,7 +72,7 @@ public interface MongoOperations {
|
||||
* @param command a MongoDB command
|
||||
*/
|
||||
CommandResult executeCommand(DBObject command);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
|
||||
* exception hierarchy.
|
||||
@@ -77,7 +81,7 @@ public interface MongoOperations {
|
||||
* @param options query options to use
|
||||
*/
|
||||
CommandResult executeCommand(DBObject command, int options);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
|
||||
*
|
||||
@@ -87,18 +91,6 @@ public interface MongoOperations {
|
||||
* @param dch the handler that will extract results, one document at a time
|
||||
*/
|
||||
void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch);
|
||||
|
||||
/**
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler using the
|
||||
* provided CursorPreparer.
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param dch the handler that will extract results, one document at a time
|
||||
* @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits,
|
||||
* skips and so on).
|
||||
*/
|
||||
void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer);
|
||||
|
||||
/**
|
||||
* Executes a {@link DbCallback} translating any exceptions as necessary.
|
||||
@@ -237,6 +229,20 @@ public interface MongoOperations {
|
||||
*/
|
||||
void dropCollection(String collectionName);
|
||||
|
||||
/**
|
||||
* Returns the operations that can be performed on indexes
|
||||
*
|
||||
* @return index operations on the named collection
|
||||
*/
|
||||
IndexOperations indexOps(String collectionName);
|
||||
|
||||
/**
|
||||
* Returns the operations that can be performed on indexes
|
||||
*
|
||||
* @return index operations on the named collection associated with the given entity class
|
||||
*/
|
||||
IndexOperations indexOps(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Query for a list of objects of type T from the collection used by the entity class.
|
||||
* <p/>
|
||||
@@ -265,11 +271,39 @@ public interface MongoOperations {
|
||||
* @return the converted collection
|
||||
*/
|
||||
<T> List<T> findAll(Class<T> entityClass, String collectionName);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
||||
* Execute a group operation over the entire collection. The group operation entity class should match the 'shape' of
|
||||
* the returned object that takes int account the initial document structure as well as any finalize functions.
|
||||
*
|
||||
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
|
||||
* considered.
|
||||
* @param inputCollectionName the collection where the group operation will read from
|
||||
* @param groupBy the conditions under which the group operation will be performed, e.g. keys, initial document,
|
||||
* reduce function.
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the group operation
|
||||
*/
|
||||
<T> GroupByResults<T> group(String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a group operation restricting the rows to those which match the provided Criteria. The group operation
|
||||
* entity class should match the 'shape' of the returned object that takes int account the initial document structure
|
||||
* as well as any finalize functions.
|
||||
*
|
||||
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
|
||||
* considered.
|
||||
* @param inputCollectionName the collection where the group operation will read from
|
||||
* @param groupBy the conditions under which the group operation will be performed, e.g. keys, initial document,
|
||||
* reduce function.
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the group operation
|
||||
*/
|
||||
<T> GroupByResults<T> group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
||||
*
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
* @param reduceFunction The JavaScript reduce function
|
||||
@@ -277,11 +311,12 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction, Class<T> entityClass );
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
Class<T> entityClass);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes additional map-reduce options.
|
||||
*
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
* @param reduceFunction The JavaScript reduce function
|
||||
@@ -289,12 +324,13 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction, MapReduceOptions mapReduceOptions, Class<T> entityClass );
|
||||
|
||||
|
||||
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
MapReduceOptions mapReduceOptions, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes a query. The map-reduce operation will be formed with an output type of INLINE
|
||||
* Execute a map-reduce operation that takes a query. The map-reduce operation will be formed with an output type of
|
||||
* INLINE
|
||||
*
|
||||
* @param query The query to use to select the data for the map phase
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
@@ -303,10 +339,12 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction, Class<T> entityClass );
|
||||
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes a query and additional map-reduce options
|
||||
*
|
||||
* @param query The query to use to select the data for the map phase
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
@@ -315,7 +353,8 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction, MapReduceOptions mapReduceOptions, Class<T> entityClass );
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
MapReduceOptions mapReduceOptions, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Returns {@link GeoResult} for all entities matching the given {@link NearQuery}. Will consider entity mapping
|
||||
@@ -338,23 +377,6 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
|
||||
* class. If not it will be created.
|
||||
*
|
||||
* @param indexDefinition
|
||||
* @param entityClass class that determines the collection to use
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition, Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists. If not it will be created.
|
||||
*
|
||||
* @param index
|
||||
* @param collectionName
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition, String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the
|
||||
* specified type.
|
||||
@@ -425,26 +447,6 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> List<T> find(Query query, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
|
||||
* <p/>
|
||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
||||
* <p/>
|
||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||
* feature rich {@link Query}.
|
||||
*
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification
|
||||
* @param entityClass the parameterized type of the returned list.
|
||||
* @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits,
|
||||
* skips and so on).
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
*
|
||||
* @return the List of converted objects.
|
||||
*/
|
||||
<T> List<T> find(Query query, Class<T> entityClass, CursorPreparer preparer, String collectionName);
|
||||
|
||||
/**
|
||||
* Returns a document with the given id mapped onto the given class. The collection the query is ran against will be
|
||||
* derived from the given target class as well.
|
||||
@@ -468,6 +470,15 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> T findById(Object id, Class<T> entityClass, String collectionName);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
|
||||
String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the
|
||||
* specified type. The first document that matches the query is returned and also removed from the collection in the
|
||||
@@ -512,7 +523,7 @@ public interface MongoOperations {
|
||||
* @return
|
||||
*/
|
||||
long count(Query query, Class<?> entityClass);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} querying the given collection.
|
||||
*
|
||||
@@ -521,7 +532,7 @@ public interface MongoOperations {
|
||||
* @return
|
||||
*/
|
||||
long count(Query query, String collectionName);
|
||||
|
||||
|
||||
/**
|
||||
* Insert the object into the collection for the entity type of the object to save.
|
||||
* <p/>
|
||||
@@ -612,6 +623,29 @@ public interface MongoOperations {
|
||||
*/
|
||||
void save(Object objectToSave, String collectionName);
|
||||
|
||||
/**
|
||||
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
|
||||
* combining the query document and the update document.
|
||||
*
|
||||
* @param query the query document that specifies the criteria used to select a record to be upserted
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
|
||||
* @param entityClass class that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult upsert(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
|
||||
* combining the query document and the update document.
|
||||
*
|
||||
* @param query the query document that specifies the criteria used to select a record to be updated
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param collectionName name of the collection to update the object in
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult upsert(Query query, Update update, String collectionName);
|
||||
|
||||
/**
|
||||
* Updates the first object that is found in the collection of the entity class that matches the query document with
|
||||
* the provided update document.
|
||||
@@ -620,6 +654,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param entityClass class that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateFirst(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
@@ -631,6 +666,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param collectionName name of the collection to update the object in
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateFirst(Query query, Update update, String collectionName);
|
||||
|
||||
@@ -642,6 +678,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param entityClass class that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateMulti(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
@@ -653,6 +690,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param collectionName name of the collection to update the object in
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateMulti(Query query, Update update, String collectionName);
|
||||
|
||||
@@ -662,7 +700,7 @@ public interface MongoOperations {
|
||||
* @param object
|
||||
*/
|
||||
void remove(Object object);
|
||||
|
||||
|
||||
/**
|
||||
* Removes the given object from the given collection.
|
||||
*
|
||||
|
||||
@@ -96,6 +96,7 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
*
|
||||
* Defaults to false
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean slaveOk = MONGO_OPTIONS.slaveOk;
|
||||
|
||||
/**
|
||||
@@ -204,6 +205,7 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
this.slaveOk = slaveOk;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void afterPropertiesSet() {
|
||||
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost;
|
||||
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* Utility methods for JSON serialization.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class SerializationUtils {
|
||||
|
||||
private SerializationUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the given object into pseudo-JSON meaning it's trying to create a JSON representation as far as possible
|
||||
* but falling back to the given object's {@link Object#toString()} method if it's not serializable. Useful for
|
||||
* printing raw {@link DBObject}s containing complex values before actually converting them into Mongo native types.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String serializeToJsonSafely(Object value) {
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.serialize(value);
|
||||
} catch (Exception e) {
|
||||
if (value instanceof Collection) {
|
||||
return toString((Collection<?>) value);
|
||||
} else if (value instanceof Map) {
|
||||
return toString((Map<?, ?>) value);
|
||||
} else if (value instanceof DBObject) {
|
||||
return toString(((DBObject) value).toMap());
|
||||
} else {
|
||||
return String.format("{ $java : %s }", value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String toString(Map<?, ?> source) {
|
||||
return iterableToDelimitedString(source.entrySet(), "{ ", " }", new Converter<Entry<?, ?>, Object>() {
|
||||
public Object convert(Entry<?, ?> source) {
|
||||
return String.format("\"%s\" : %s", source.getKey(), serializeToJsonSafely(source.getValue()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String toString(Collection<?> source) {
|
||||
return iterableToDelimitedString(source, "[ ", " ]", new Converter<Object, Object>() {
|
||||
public Object convert(Object source) {
|
||||
return serializeToJsonSafely(source);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation from the given {@link Iterable} prepending the postfix, applying the given
|
||||
* {@link Converter} to each element before adding it to the result {@link String}, concatenating each element with
|
||||
* {@literal ,} and applying the postfix.
|
||||
*
|
||||
* @param source
|
||||
* @param prefix
|
||||
* @param postfix
|
||||
* @param transformer
|
||||
* @return
|
||||
*/
|
||||
private static <T> String iterableToDelimitedString(Iterable<T> source, String prefix, String postfix,
|
||||
Converter<? super T, Object> transformer) {
|
||||
|
||||
StringBuilder builder = new StringBuilder(prefix);
|
||||
Iterator<T> iterator = source.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
builder.append(transformer.convert(iterator.next()));
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
return builder.append(postfix).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,6 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
@@ -39,12 +37,10 @@ import com.mongodb.WriteConcern;
|
||||
*/
|
||||
public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Mongo mongo;
|
||||
private final String databaseName;
|
||||
private String username;
|
||||
private String password;
|
||||
private final boolean mongoInstanceCreated;
|
||||
private final UserCredentials credentials;
|
||||
private WriteConcern writeConcern;
|
||||
|
||||
/**
|
||||
@@ -54,11 +50,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* @param databaseName database name, not be {@literal null}.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||
Assert.notNull(mongo, "Mongo must not be null");
|
||||
Assert.hasText(databaseName, "Database name must not be empty");
|
||||
Assert.isTrue(databaseName.matches("[\\w-]+"), "Database name must only contain letters, numbers, underscores and dashes!");
|
||||
this.mongo = mongo;
|
||||
this.databaseName = databaseName;
|
||||
this(mongo, databaseName, UserCredentials.NO_CREDENTIALS, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,14 +58,12 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null}.
|
||||
* @param userCredentials username and password must not be {@literal null}.
|
||||
* @param credentials username and password.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials userCredentials) {
|
||||
this(mongo, databaseName);
|
||||
this.username = userCredentials.getUsername();
|
||||
this.password = userCredentials.getPassword();
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||
this(mongo, databaseName, credentials, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoURI}.
|
||||
*
|
||||
@@ -83,8 +73,21 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* @see MongoURI
|
||||
*/
|
||||
public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException {
|
||||
|
||||
this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), String.valueOf(uri.getPassword())));
|
||||
this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())), true);
|
||||
}
|
||||
|
||||
private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
||||
boolean mongoInstanceCreated) {
|
||||
|
||||
Assert.notNull(mongo, "Mongo must not be null");
|
||||
Assert.hasText(databaseName, "Database name must not be empty");
|
||||
Assert.isTrue(databaseName.matches("[\\w-]+"),
|
||||
"Database name must only contain letters, numbers, underscores and dashes!");
|
||||
|
||||
this.mongo = mongo;
|
||||
this.databaseName = databaseName;
|
||||
this.mongoInstanceCreated = mongoInstanceCreated;
|
||||
this.credentials = credentials == null ? UserCredentials.NO_CREDENTIALS : credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +115,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
|
||||
Assert.hasText(dbName, "Database name must not be empty.");
|
||||
|
||||
DB db = MongoDbUtils.getDB(mongo, dbName, username, password == null ? null : password.toCharArray());
|
||||
DB db = MongoDbUtils.getDB(mongo, dbName, credentials);
|
||||
|
||||
if (writeConcern != null) {
|
||||
db.setWriteConcern(writeConcern);
|
||||
@@ -122,9 +125,17 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the Mongo instance.
|
||||
* Clean up the Mongo instance if it was created by the factory itself.
|
||||
*
|
||||
* @see DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
mongo.close();
|
||||
if (mongoInstanceCreated) {
|
||||
mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseChars(char[] chars) {
|
||||
return chars == null ? null : String.valueOf(chars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* A strategy interface to determine the WriteConcern to use for a given MongoDbAction.
|
||||
*
|
||||
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public interface WriteConcernResolver {
|
||||
|
||||
/**
|
||||
* Resolve the WriteConcern given the MongoAction
|
||||
*
|
||||
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
|
||||
* be resolved.
|
||||
* @return a WriteConcern based on the passed in MongoAction value, maybe null
|
||||
*/
|
||||
WriteConcern resolve(MongoAction action);
|
||||
}
|
||||
@@ -17,16 +17,16 @@
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObjectIdConverter;
|
||||
|
||||
/**
|
||||
@@ -40,16 +40,17 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
|
||||
protected final GenericConversionService conversionService;
|
||||
protected CustomConversions conversions = new CustomConversions();
|
||||
protected EntityInstantiators instantiators = new EntityInstantiators();
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractMongoConverter} using the given {@link GenericConversionService}.
|
||||
*
|
||||
* @param conversionService
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public AbstractMongoConverter(GenericConversionService conversionService) {
|
||||
this.conversionService = conversionService == null ? ConversionServiceFactory.createDefaultConversionService()
|
||||
: conversionService;
|
||||
this.conversionService.removeConvertible(Object.class, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,15 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
this.conversions = conversions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers {@link EntityInstantiators} to customize entity instantiation.
|
||||
*
|
||||
* @param instantiators
|
||||
*/
|
||||
public void setInstantiators(EntityInstantiators instantiators) {
|
||||
this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers additional converters that will be available when using the {@link ConversionService} directly (e.g. for
|
||||
* id conversion). These converters are not custom conversions as they'd introduce unwanted conversions (e.g.
|
||||
@@ -80,12 +90,6 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) {
|
||||
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
|
||||
}
|
||||
if (!conversionService.canConvert(BigInteger.class, String.class)) {
|
||||
conversionService.addConverter(BigIntegerToStringConverter.INSTANCE);
|
||||
}
|
||||
if (!conversionService.canConvert(String.class, BigInteger.class)) {
|
||||
conversionService.addConverter(StringToBigIntegerConverter.INSTANCE);
|
||||
}
|
||||
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Conversion registration information.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class ConverterRegistration {
|
||||
|
||||
private final ConvertiblePair convertiblePair;
|
||||
private final boolean reading;
|
||||
private final boolean writing;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterRegistration}.
|
||||
*
|
||||
* @param convertiblePair must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWritingwhether to force to consider the converter for reading.
|
||||
*/
|
||||
public ConverterRegistration(ConvertiblePair convertiblePair, boolean isReading, boolean isWriting) {
|
||||
|
||||
Assert.notNull(convertiblePair);
|
||||
|
||||
this.convertiblePair = convertiblePair;
|
||||
this.reading = isReading;
|
||||
this.writing = isWriting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterRegistration} from the given source and target type and read/write flags.
|
||||
*
|
||||
* @param source the source type to be converted from, must not be {@literal null}.
|
||||
* @param target the target type to be converted to, must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWriting whether to force to consider the converter for writing.
|
||||
*/
|
||||
public ConverterRegistration(Class<?> source, Class<?> target, boolean isReading, boolean isWriting) {
|
||||
this(new ConvertiblePair(source, target), isReading, isWriting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for writing.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isWriting() {
|
||||
return writing == true || (!reading && isSimpleTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for reading.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isReading() {
|
||||
return reading == true || (!writing && isSimpleSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual conversion pair.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ConvertiblePair getConvertiblePair() {
|
||||
return convertiblePair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source type is a Mongo simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleSourceType() {
|
||||
return isMongoBasicType(convertiblePair.getSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target type is a Mongo simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleTargetType() {
|
||||
return isMongoBasicType(convertiblePair.getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Mongo can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static boolean isMongoBasicType(Class<?> type) {
|
||||
return MongoSimpleTypes.HOLDER.isSimpleType(type);
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,13 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -31,14 +31,18 @@ import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.URLToStringConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Value object to capture custom conversion. That is essentially a {@link List} of converters and some additional logic
|
||||
* around them. The converters are pretty much builds up two sets of types which Mongo basic types {@see #MONGO_TYPES}
|
||||
@@ -50,9 +54,9 @@ import com.mongodb.DBObject;
|
||||
*/
|
||||
public class CustomConversions {
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, ObjectId.class,
|
||||
String.class, DBObject.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CustomConversions.class);
|
||||
private static final String READ_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as reading converter although it doesn't convert from a Mongo supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
private static final String WRITE_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as writing converter although it doesn't convert to a Mongo supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
|
||||
private final Set<ConvertiblePair> readingPairs;
|
||||
private final Set<ConvertiblePair> writingPairs;
|
||||
@@ -85,6 +89,10 @@ public class CustomConversions {
|
||||
this.converters.add(CustomToStringConverter.INSTANCE);
|
||||
this.converters.add(BigDecimalToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToBigDecimalConverter.INSTANCE);
|
||||
this.converters.add(BigIntegerToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToBigIntegerConverter.INSTANCE);
|
||||
this.converters.add(URLToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToURLConverter.INSTANCE);
|
||||
this.converters.addAll(converters);
|
||||
|
||||
for (Object c : this.converters) {
|
||||
@@ -155,14 +163,18 @@ public class CustomConversions {
|
||||
*/
|
||||
private void registerConversion(Object converter) {
|
||||
|
||||
Class<?> type = converter.getClass();
|
||||
boolean isWriting = type.isAnnotationPresent(WritingConverter.class);
|
||||
boolean isReading = type.isAnnotationPresent(ReadingConverter.class);
|
||||
|
||||
if (converter instanceof GenericConverter) {
|
||||
GenericConverter genericConverter = (GenericConverter) converter;
|
||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(pair);
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConvertiblePair(arguments[0], arguments[1]));
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported Converter type!");
|
||||
}
|
||||
@@ -174,15 +186,27 @@ public class CustomConversions {
|
||||
*
|
||||
* @param pair
|
||||
*/
|
||||
private void register(ConvertiblePair pair) {
|
||||
private void register(ConverterRegistration context) {
|
||||
|
||||
ConvertiblePair pair = context.getConvertiblePair();
|
||||
|
||||
if (context.isReading()) {
|
||||
|
||||
if (isMongoBasicType(pair.getSourceType())) {
|
||||
readingPairs.add(pair);
|
||||
|
||||
if (LOG.isWarnEnabled() && !context.isSimpleSourceType()) {
|
||||
LOG.warn(String.format(READ_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
|
||||
if (isMongoBasicType(pair.getTargetType())) {
|
||||
if (context.isWriting()) {
|
||||
|
||||
writingPairs.add(pair);
|
||||
customSimpleTypes.add(pair.getSourceType());
|
||||
|
||||
if (LOG.isWarnEnabled() && !context.isSimpleTargetType()) {
|
||||
LOG.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +223,7 @@ public class CustomConversions {
|
||||
|
||||
/**
|
||||
* Returns the target type we can write an onject of the given source type to. The returned type might be a subclass
|
||||
* oth the given expected type though. If {@code expexctedTargetType} is {@literal null} we will simply return the
|
||||
* oth the given expected type though. If {@code expectedTargetType} is {@literal null} we will simply return the
|
||||
* first target type matching or {@literal null} if no conversion can be found.
|
||||
*
|
||||
* @param source must not be {@literal null}
|
||||
@@ -273,16 +297,7 @@ public class CustomConversions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Mongo can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static boolean isMongoBasicType(Class<?> type) {
|
||||
return MONGO_TYPES.contains(type);
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
private enum CustomToStringConverter implements GenericConverter {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link PropertyAccessor} to allow entity based field access to {@link DBObject}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class DBObjectPropertyAccessor extends MapAccessor {
|
||||
|
||||
static MapAccessor INSTANCE = new DBObjectPropertyAccessor();
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class[] { DBObject.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead(EvaluationContext context, Object target, String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public TypedValue read(EvaluationContext context, Object target, String name) {
|
||||
|
||||
Map<String, Object> source = (Map<String, Object>) target;
|
||||
|
||||
Object value = source.get(name);
|
||||
return value == null ? TypedValue.NULL : new TypedValue(value);
|
||||
}
|
||||
}
|
||||
@@ -50,23 +50,22 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
||||
public DefaultMongoTypeMapper() {
|
||||
this(DEFAULT_TYPE_KEY, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
}
|
||||
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey));
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?,?>, ?> mappingContext) {
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey), mappers);
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#isTypeKey(java.lang.String)
|
||||
@@ -75,7 +74,6 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
||||
return typeKey == null ? false : typeKey.equals(key);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
||||
*/
|
||||
@@ -83,29 +81,29 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
||||
protected TypeInformation<?> getFallbackTypeFor(DBObject source) {
|
||||
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static final class DBObjectTypeAliasAccessor implements TypeAliasAccessor<DBObject> {
|
||||
|
||||
|
||||
private final String typeKey;
|
||||
|
||||
|
||||
public DBObjectTypeAliasAccessor(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
|
||||
*/
|
||||
public Object readAliasFrom(DBObject source) {
|
||||
|
||||
|
||||
if (source instanceof BasicDBList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return source.get(typeKey);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 by the original author(s).
|
||||
* Copyright 2011-2012 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,48 +15,44 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELAwareParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -74,18 +70,9 @@ import com.mongodb.DBRef;
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, TypeKeyAware {
|
||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<Map> MAP_TYPE_INFORMATION = ClassTypeInformation.from(Map.class);
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<Collection> COLLECTION_TYPE_INFORMATION = ClassTypeInformation
|
||||
.from(Collection.class);
|
||||
|
||||
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[] { ObjectId.class, String.class,
|
||||
BigInteger.class, byte[].class });
|
||||
|
||||
protected static final Log log = LogFactory.getLog(MappingMongoConverter.class);
|
||||
protected static final Logger log = LoggerFactory.getLogger(MappingMongoConverter.class);
|
||||
|
||||
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
protected final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
@@ -94,6 +81,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
protected ApplicationContext applicationContext;
|
||||
protected boolean useFieldAccessOnly = true;
|
||||
protected MongoTypeMapper typeMapper;
|
||||
protected String mapKeyDotReplacement = null;
|
||||
|
||||
private SpELContext spELContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}.
|
||||
@@ -101,6 +91,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public MappingMongoConverter(MongoDbFactory mongoDbFactory,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
@@ -112,7 +103,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.mappingContext = mappingContext;
|
||||
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
|
||||
this.idMapper = new QueryMapper(conversionService);
|
||||
this.idMapper = new QueryMapper(this);
|
||||
|
||||
this.spELContext = new SpELContext(DBObjectPropertyAccessor.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,12 +121,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
mappingContext) : typeMapper;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.TypeKeyAware#isTypeKey(java.lang.String)
|
||||
/**
|
||||
* Configure the characters dots potentially contained in a {@link Map} shall be replaced with. By default we don't do
|
||||
* any translation but rather reject a {@link Map} with keys containing dots causing the conversion for the entire
|
||||
* object to fail. If further customization of the translation is needed, have a look at
|
||||
* {@link #potentiallyEscapeMapKey(String)} as well as {@link #potentiallyUnescapeMapKey(String)}.
|
||||
*
|
||||
* @param mapKeyDotReplacement the mapKeyDotReplacement to set
|
||||
*/
|
||||
public boolean isTypeKey(String key) {
|
||||
return typeMapper.isTypeKey(key);
|
||||
public void setMapKeyDotReplacement(String mapKeyDotReplacement) {
|
||||
this.mapKeyDotReplacement = mapKeyDotReplacement;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -160,7 +157,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.applicationContext = applicationContext;
|
||||
this.spELContext = new SpELContext(this.spELContext, applicationContext);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,8 +170,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return read(ClassTypeInformation.from(clazz), dbo);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
|
||||
return read(type, dbo, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo, Object parent) {
|
||||
|
||||
if (null == dbo) {
|
||||
return null;
|
||||
@@ -185,12 +188,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return conversionService.convert(dbo, rawType);
|
||||
}
|
||||
|
||||
if (DBObject.class.isAssignableFrom(rawType)) {
|
||||
return (S) dbo;
|
||||
}
|
||||
|
||||
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
|
||||
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo);
|
||||
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo, parent);
|
||||
}
|
||||
|
||||
if (typeToUse.isMap()) {
|
||||
return (S) readMap(typeToUse, dbo);
|
||||
return (S) readMap(typeToUse, dbo, parent);
|
||||
}
|
||||
|
||||
// Retrieve persistent entity info
|
||||
@@ -200,79 +207,44 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
throw new MappingException("No mapping metadata found for " + rawType.getName());
|
||||
}
|
||||
|
||||
return read(persistentEntity, dbo);
|
||||
return read(persistentEntity, dbo, parent);
|
||||
}
|
||||
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
|
||||
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
|
||||
DBObject source, DefaultSpELExpressionEvaluator evaluator, Object parent) {
|
||||
|
||||
final StandardEvaluationContext spelCtx = new StandardEvaluationContext();
|
||||
if (null != applicationContext) {
|
||||
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
}
|
||||
if (!(dbo instanceof BasicDBList)) {
|
||||
String[] keySet = dbo.keySet().toArray(new String[dbo.keySet().size()]);
|
||||
for (String key : keySet) {
|
||||
spelCtx.setVariable(key, dbo.get(key));
|
||||
}
|
||||
}
|
||||
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, parent);
|
||||
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
|
||||
entity, provider, parent);
|
||||
parameterProvider.setSpELEvaluator(evaluator);
|
||||
|
||||
final List<String> ctorParamNames = new ArrayList<String>();
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
return parameterProvider;
|
||||
}
|
||||
|
||||
ParameterValueProvider provider = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, Object parent) {
|
||||
|
||||
if (parameter.getKey() != null) {
|
||||
return super.getParameterValue(parameter);
|
||||
}
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(dbo, spELContext);
|
||||
|
||||
String name = parameter.getName();
|
||||
TypeInformation<T> type = parameter.getType();
|
||||
Class<T> rawType = parameter.getRawType();
|
||||
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getFieldName() : name;
|
||||
Object obj = dbo.get(key);
|
||||
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, dbo, evaluator, parent);
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, provider);
|
||||
|
||||
ctorParamNames.add(name);
|
||||
if (obj instanceof DBRef) {
|
||||
return read(type, ((DBRef) obj).fetch());
|
||||
} else if (obj instanceof BasicDBList) {
|
||||
BasicDBList objAsDbList = (BasicDBList) obj;
|
||||
return conversionService.convert(readCollectionOrArray(type, objAsDbList), rawType);
|
||||
} else if (obj instanceof DBObject) {
|
||||
return read(type, ((DBObject) obj));
|
||||
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
|
||||
return (T) obj;
|
||||
} else if (null != obj) {
|
||||
return conversionService.convert(obj, rawType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(entity, provider, conversionService);
|
||||
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
final S result = wrapper.getBean();
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||
|
||||
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
|
||||
boolean isConstructorProperty = entity.isConstructorArgument(prop);
|
||||
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
||||
|
||||
if (!hasValueForProperty || isConstructorProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = getValueInternal(prop, dbo, spelCtx, prop.getSpelExpression());
|
||||
try {
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
Object obj = getValueInternal(prop, dbo, evaluator, result);
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -280,7 +252,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
Object obj = getValueInternal(inverseProp, dbo, spelCtx, inverseProp.getSpelExpression());
|
||||
Object obj = getValueInternal(inverseProp, dbo, evaluator, result);
|
||||
try {
|
||||
wrapper.setProperty(inverseProp, obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -291,7 +263,23 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
});
|
||||
|
||||
return wrapper.getBean();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#toDBRef(java.lang.Object, org.springframework.data.mongodb.core.mapping.MongoPersistentProperty)
|
||||
*/
|
||||
public DBRef toDBRef(Object object, MongoPersistentProperty referingProperty) {
|
||||
|
||||
org.springframework.data.mongodb.core.mapping.DBRef annotation = null;
|
||||
|
||||
if (referingProperty != null) {
|
||||
annotation = referingProperty.getDBRef();
|
||||
Assert.isTrue(annotation != null, "The referenced property has to be mapped with @DBRef!");
|
||||
}
|
||||
|
||||
return createDBRef(object, annotation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,7 +296,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
boolean handledByCustomConverter = conversions.getCustomWriteTarget(obj.getClass(), DBObject.class) != null;
|
||||
TypeInformation<? extends Object> type = ClassTypeInformation.from(obj.getClass());
|
||||
|
||||
|
||||
if (!handledByCustomConverter && !(dbo instanceof BasicDBList)) {
|
||||
typeMapper.writeType(type, dbo);
|
||||
}
|
||||
@@ -338,12 +326,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(obj.getClass())) {
|
||||
writeMapInternal((Map<Object, Object>) obj, dbo, MAP_TYPE_INFORMATION);
|
||||
writeMapInternal((Map<Object, Object>) obj, dbo, ClassTypeInformation.MAP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(obj.getClass())) {
|
||||
writeCollectionInternal((Collection<?>) obj, COLLECTION_TYPE_INFORMATION, (BasicDBList) dbo);
|
||||
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) dbo);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -367,46 +355,24 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
// Write the ID
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
if (!dbo.containsField("_id") && null != idProperty) {
|
||||
Object idObj = null;
|
||||
Class<?>[] targetClasses = new Class<?>[] { ObjectId.class, String.class, Object.class };
|
||||
for (Class<?> targetClass : targetClasses) {
|
||||
try {
|
||||
idObj = wrapper.getProperty(idProperty, targetClass, useFieldAccessOnly);
|
||||
if (null != idObj) {
|
||||
break;
|
||||
}
|
||||
} catch (ConversionException ignored) {
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (null != idObj) {
|
||||
dbo.put("_id", idObj);
|
||||
} else {
|
||||
if (!VALID_ID_TYPES.contains(idProperty.getType())) {
|
||||
throw new MappingException("Invalid data type " + idProperty.getType().getName()
|
||||
+ " for Id property. Should be one of " + VALID_ID_TYPES);
|
||||
}
|
||||
try {
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
dbo.put("_id", idMapper.convertId(id));
|
||||
} catch (ConversionException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
// Write the properties
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||
|
||||
if (prop.equals(idProperty)) {
|
||||
return;
|
||||
}
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
|
||||
if (null != propertyObj) {
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
writePropertyInternal(propertyObj, dbo, prop);
|
||||
@@ -421,14 +387,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
Class<?> type = inverseProp.getType();
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = wrapper.getProperty(inverseProp, type, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
Object propertyObj = wrapper.getProperty(inverseProp, type, useFieldAccessOnly);
|
||||
if (null != propertyObj) {
|
||||
writePropertyInternal(propertyObj, dbo, inverseProp);
|
||||
}
|
||||
@@ -444,16 +403,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
String name = prop.getFieldName();
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (prop.isCollection()) {
|
||||
if (valueType.isCollectionLike()) {
|
||||
DBObject collectionInternal = createCollection(asCollection(obj), prop);
|
||||
dbo.put(name, collectionInternal);
|
||||
return;
|
||||
}
|
||||
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (prop.isMap()) {
|
||||
if (valueType.isMap()) {
|
||||
BasicDBObject mapDbObj = new BasicDBObject();
|
||||
writeMapInternal((Map<Object, Object>) obj, mapDbObj, type);
|
||||
dbo.put(name, mapDbObj);
|
||||
@@ -512,7 +471,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @param collection must not be {@literal null}.
|
||||
* @param property must not be {@literal null}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
||||
@@ -550,13 +508,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
for (Object element : source) {
|
||||
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
Class<?> elementType = element == null ? null : element.getClass();
|
||||
|
||||
Class<?> elementType = element.getClass();
|
||||
|
||||
if (conversions.isSimpleType(elementType)) {
|
||||
if (elementType == null || conversions.isSimpleType(elementType)) {
|
||||
sink.add(getPotentiallyConvertedSimpleWrite(element));
|
||||
} else if (element instanceof Collection || elementType.isArray()) {
|
||||
sink.add(writeCollectionInternal(asCollection(element), componentType, new BasicDBList()));
|
||||
@@ -579,32 +533,67 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @return
|
||||
*/
|
||||
protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {
|
||||
|
||||
|
||||
for (Map.Entry<Object, Object> entry : obj.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
if (conversions.isSimpleType(key.getClass())) {
|
||||
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
|
||||
// being convertable
|
||||
String simpleKey = key.toString();
|
||||
String simpleKey = potentiallyEscapeMapKey(key.toString());
|
||||
if (val == null || conversions.isSimpleType(val.getClass())) {
|
||||
writeSimpleInternal(val, dbo, simpleKey);
|
||||
} else if (val instanceof Collection) {
|
||||
} else if (val instanceof Collection || val.getClass().isArray()) {
|
||||
dbo.put(simpleKey,
|
||||
writeCollectionInternal((Collection<?>) val, propertyType.getMapValueType(), new BasicDBList()));
|
||||
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
|
||||
} else {
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
writeInternal(val, newDbo, propertyType);
|
||||
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: ClassTypeInformation.OBJECT;
|
||||
writeInternal(val, newDbo, valueTypeInfo);
|
||||
dbo.put(simpleKey, newDbo);
|
||||
}
|
||||
} else {
|
||||
throw new MappingException("Cannot use a complex object as a key value.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return dbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially replaces dots in the given map key with the configured map key replacement if configured or aborts
|
||||
* conversion if none is configured.
|
||||
*
|
||||
* @see #setMapKeyDotReplacement(String)
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
protected String potentiallyEscapeMapKey(String source) {
|
||||
|
||||
if (!source.contains(".")) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (mapKeyDotReplacement == null) {
|
||||
throw new MappingException(String.format("Map key %s contains dots but no replacement was configured! Make "
|
||||
+ "sure map keys don't contain dots in the first place or configure an appropriate replacement!", source));
|
||||
}
|
||||
|
||||
return source.replaceAll("\\.", mapKeyDotReplacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the map key replacements in the given key just read with a dot in case a map key replacement has been
|
||||
* configured.
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
protected String potentiallyUnescapeMapKey(String source) {
|
||||
return mapKeyDotReplacement == null ? source : source.replaceAll(mapKeyDotReplacement, "\\.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds custom type information to the given {@link DBObject} if necessary. That is if the value is not the same as
|
||||
* the one given. This is usually the case if you store a subtype of the actual declared type of the property.
|
||||
@@ -653,7 +642,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
if (customTarget != null) {
|
||||
return conversionService.convert(value, customTarget);
|
||||
} else {
|
||||
return value.getClass().isEnum() ? ((Enum<?>) value).name() : value;
|
||||
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,7 +665,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return conversionService.convert(value, target);
|
||||
}
|
||||
|
||||
if (target.isEnum()) {
|
||||
if (Enum.class.isAssignableFrom(target)) {
|
||||
return Enum.valueOf((Class<Enum>) target, value.toString());
|
||||
}
|
||||
|
||||
@@ -685,89 +674,38 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
protected DBRef createDBRef(Object target, org.springframework.data.mongodb.core.mapping.DBRef dbref) {
|
||||
|
||||
Assert.notNull(target);
|
||||
|
||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
if (null == targetEntity || null == targetEntity.getIdProperty()) {
|
||||
return null;
|
||||
|
||||
if (null == targetEntity) {
|
||||
throw new MappingException("No mapping metadata found for " + target.getClass());
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProperty = targetEntity.getIdProperty();
|
||||
Object id = null;
|
||||
|
||||
if (idProperty == null) {
|
||||
throw new MappingException("No id property found on class " + targetEntity.getType());
|
||||
}
|
||||
|
||||
BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(target, conversionService);
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
|
||||
try {
|
||||
id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
|
||||
String collection = dbref.collection();
|
||||
if ("".equals(collection)) {
|
||||
collection = targetEntity.getCollection();
|
||||
}
|
||||
DB db = mongoDbFactory.getDb();
|
||||
db = dbref != null && StringUtils.hasText(dbref.db()) ? mongoDbFactory.getDb(dbref.db()) : db;
|
||||
|
||||
String dbname = dbref.db();
|
||||
DB db = StringUtils.hasText(dbname) ? mongoDbFactory.getDb(dbname) : mongoDbFactory.getDb();
|
||||
|
||||
return new DBRef(db, collection, idMapper.convertId(id));
|
||||
return new DBRef(db, targetEntity.getCollection(), idMapper.convertId(id));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx,
|
||||
String spelExpr) {
|
||||
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator eval,
|
||||
Object parent) {
|
||||
|
||||
Object o;
|
||||
if (null != spelExpr) {
|
||||
Expression x = spelExpressionParser.parseExpression(spelExpr);
|
||||
o = x.getValue(ctx);
|
||||
} else {
|
||||
|
||||
Object sourceValue = dbo.get(prop.getFieldName());
|
||||
|
||||
if (sourceValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> propertyType = prop.getType();
|
||||
|
||||
if (conversions.hasCustomReadTarget(sourceValue.getClass(), propertyType)) {
|
||||
return conversionService.convert(sourceValue, propertyType);
|
||||
}
|
||||
|
||||
if (sourceValue instanceof DBRef) {
|
||||
sourceValue = ((DBRef) sourceValue).fetch();
|
||||
}
|
||||
if (sourceValue instanceof DBObject) {
|
||||
if (prop.isMap()) {
|
||||
return readMap(prop.getTypeInformation(), (DBObject) sourceValue);
|
||||
} else if (prop.isArray() && sourceValue instanceof BasicDBObject
|
||||
&& ((DBObject) sourceValue).keySet().size() == 0) {
|
||||
// It's empty
|
||||
return Array.newInstance(prop.getComponentType(), 0);
|
||||
} else if (prop.isCollection() && sourceValue instanceof BasicDBList) {
|
||||
return readCollectionOrArray((TypeInformation<? extends Collection<?>>) prop.getTypeInformation(),
|
||||
(BasicDBList) sourceValue);
|
||||
}
|
||||
|
||||
TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue);
|
||||
|
||||
// It's a complex object, have to read it in
|
||||
if (toType != null) {
|
||||
// TODO: why do we remove the type?
|
||||
// dbo.removeField(CUSTOM_TYPE_KEY);
|
||||
o = read(toType, (DBObject) sourceValue);
|
||||
} else {
|
||||
o = read(mappingContext.getPersistentEntity(prop.getTypeInformation()), (DBObject) sourceValue);
|
||||
}
|
||||
} else {
|
||||
o = sourceValue;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(dbo, spELContext, parent);
|
||||
return provider.getPropertyValue(prop);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -775,28 +713,40 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @param targetType must not be {@literal null}.
|
||||
* @param sourceValue must not be {@literal null}.
|
||||
* @return the converted {@link Collections}, will never be {@literal null}.
|
||||
* @return the converted {@link Collection} or array, will never be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Collection<?> readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue) {
|
||||
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, Object parent) {
|
||||
|
||||
Assert.notNull(targetType);
|
||||
|
||||
if (sourceValue.isEmpty()) {
|
||||
return new HashSet<Object>();
|
||||
}
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||
.createCollection(targetType.getType(), sourceValue.size());
|
||||
.createCollection(collectionType, sourceValue.size());
|
||||
TypeInformation<?> componentType = targetType.getComponentType();
|
||||
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
|
||||
|
||||
for (int i = 0; i < sourceValue.size(); i++) {
|
||||
|
||||
Object dbObjItem = sourceValue.get(i);
|
||||
|
||||
if (dbObjItem instanceof DBRef) {
|
||||
items.add(read(targetType.getComponentType(), ((DBRef) dbObjItem).fetch()));
|
||||
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, ((DBRef) dbObjItem).fetch(),
|
||||
parent));
|
||||
} else if (dbObjItem instanceof DBObject) {
|
||||
items.add(read(targetType.getComponentType(), (DBObject) dbObjItem));
|
||||
items.add(read(componentType, (DBObject) dbObjItem, parent));
|
||||
} else {
|
||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, targetType.getComponentType().getType()));
|
||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
return getPotentiallyConvertedSimpleRead(items, targetType.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -807,7 +757,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<Object, Object> readMap(TypeInformation<?> type, DBObject dbObject) {
|
||||
protected Map<Object, Object> readMap(TypeInformation<?> type, DBObject dbObject, Object parent) {
|
||||
|
||||
Assert.notNull(dbObject);
|
||||
|
||||
@@ -820,19 +770,22 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
continue;
|
||||
}
|
||||
|
||||
Object key = entry.getKey();
|
||||
Object key = potentiallyUnescapeMapKey(entry.getKey());
|
||||
|
||||
TypeInformation<?> keyTypeInformation = type.getComponentType();
|
||||
if (keyTypeInformation != null) {
|
||||
Class<?> keyType = keyTypeInformation.getType();
|
||||
key = conversionService.convert(entry.getKey(), keyType);
|
||||
key = conversionService.convert(key, keyType);
|
||||
}
|
||||
|
||||
Object value = entry.getValue();
|
||||
TypeInformation<?> valueType = type.getMapValueType();
|
||||
Class<?> rawValueType = valueType == null ? null : valueType.getType();
|
||||
|
||||
if (value instanceof DBObject) {
|
||||
map.put(key, read(valueType, (DBObject) value));
|
||||
map.put(key, read(valueType, (DBObject) value, parent));
|
||||
} else if (value instanceof DBRef) {
|
||||
map.put(key, DBRef.class.equals(rawValueType) ? value : read(valueType, ((DBRef) value).fetch()));
|
||||
} else {
|
||||
Class<?> valueClass = valueType == null ? null : valueType.getType();
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
|
||||
@@ -864,7 +817,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> target = conversions.getCustomWriteTarget(getClass());
|
||||
Class<?> target = conversions.getCustomWriteTarget(obj.getClass());
|
||||
if (target != null) {
|
||||
return conversionService.convert(obj, target);
|
||||
}
|
||||
@@ -888,46 +841,119 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (obj instanceof Map) {
|
||||
Map<Object, Object> m = new HashMap<Object, Object>();
|
||||
DBObject result = new BasicDBObject();
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||
m.put(entry.getKey(), convertToMongoType(entry.getValue()));
|
||||
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue()));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
if (obj instanceof List) {
|
||||
List<?> l = (List<?>) obj;
|
||||
List<Object> newList = new ArrayList<Object>();
|
||||
for (Object o : l) {
|
||||
newList.add(convertToMongoType(o));
|
||||
}
|
||||
return newList;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (obj.getClass().isArray()) {
|
||||
return maybeConvertArray((Object[]) obj);
|
||||
return maybeConvertList(Arrays.asList((Object[]) obj));
|
||||
}
|
||||
|
||||
if (obj instanceof Collection) {
|
||||
return maybeConvertList((Collection<?>) obj);
|
||||
}
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
this.write(obj, newDbo);
|
||||
return newDbo;
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
public Object[] maybeConvertArray(Object[] src) {
|
||||
Object[] newArr = new Object[src.length];
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
newArr[i] = convertToMongoType(src[i]);
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
|
||||
public BasicDBList maybeConvertList(BasicDBList dbl) {
|
||||
public BasicDBList maybeConvertList(Iterable<?> source) {
|
||||
BasicDBList newDbl = new BasicDBList();
|
||||
Iterator<?> iter = dbl.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object o = iter.next();
|
||||
newDbl.add(convertToMongoType(o));
|
||||
for (Object element : source) {
|
||||
newDbl.add(convertToMongoType(element));
|
||||
}
|
||||
return newDbl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the type information from the conversion result.
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
private Object removeTypeInfoRecursively(Object object) {
|
||||
|
||||
if (!(object instanceof DBObject)) {
|
||||
return object;
|
||||
}
|
||||
|
||||
DBObject dbObject = (DBObject) object;
|
||||
String keyToRemove = null;
|
||||
for (String key : dbObject.keySet()) {
|
||||
|
||||
if (typeMapper.isTypeKey(key)) {
|
||||
keyToRemove = key;
|
||||
}
|
||||
|
||||
Object value = dbObject.get(key);
|
||||
if (value instanceof BasicDBList) {
|
||||
for (Object element : (BasicDBList) value) {
|
||||
removeTypeInfoRecursively(element);
|
||||
}
|
||||
} else {
|
||||
removeTypeInfoRecursively(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyToRemove != null) {
|
||||
dbObject.removeField(keyToRemove);
|
||||
}
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
|
||||
private class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
|
||||
|
||||
private final DBObject source;
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final Object parent;
|
||||
|
||||
public MongoDbPropertyValueProvider(DBObject source, SpELContext factory, Object parent) {
|
||||
this(source, new DefaultSpELExpressionEvaluator(source, factory), parent);
|
||||
}
|
||||
|
||||
public MongoDbPropertyValueProvider(DBObject source, DefaultSpELExpressionEvaluator evaluator, Object parent) {
|
||||
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(evaluator);
|
||||
|
||||
this.source = source;
|
||||
this.evaluator = evaluator;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||
|
||||
String expression = property.getSpelExpression();
|
||||
Object value = expression != null ? evaluator.evaluate(expression) : source.get(property.getFieldName());
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeInformation<?> type = property.getTypeInformation();
|
||||
Class<?> rawType = type.getType();
|
||||
|
||||
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
|
||||
return (T) conversionService.convert(value, rawType);
|
||||
} else if (value instanceof DBRef) {
|
||||
return (T) (rawType.equals(DBRef.class) ? value : read(type, ((DBRef) value).fetch(), parent));
|
||||
} else if (value instanceof BasicDBList) {
|
||||
return (T) readCollectionOrArray(type, (BasicDBList) value, parent);
|
||||
} else if (value instanceof DBObject) {
|
||||
return (T) read(type, (DBObject) value, parent);
|
||||
} else {
|
||||
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,12 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -119,4 +123,28 @@ abstract class MongoConverters {
|
||||
return StringUtils.hasText(source) ? new BigInteger(source) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum URLToStringConverter implements Converter<URL, String> {
|
||||
INSTANCE;
|
||||
|
||||
public String convert(URL source) {
|
||||
return source == null ? null : source.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static enum StringToURLConverter implements Converter<String, URL> {
|
||||
INSTANCE;
|
||||
|
||||
private static final TypeDescriptor SOURCE = TypeDescriptor.valueOf(String.class);
|
||||
private static final TypeDescriptor TARGET = TypeDescriptor.valueOf(URL.class);
|
||||
|
||||
public URL convert(String source) {
|
||||
|
||||
try {
|
||||
return source == null ? null : new URL(source);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ConversionFailedException(SOURCE, TARGET, source, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,16 @@ import org.springframework.data.convert.TypeMapper;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Combining interface to express Mongo specific {@link TypeMapper} implementations will be {@link TypeKeyAware} as
|
||||
* well.
|
||||
* Mongo-specific {@link TypeMapper} exposing that {@link DBObject}s might contain a type key.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoTypeMapper extends TypeMapper<DBObject>, TypeKeyAware {
|
||||
public interface MongoTypeMapper extends TypeMapper<DBObject> {
|
||||
|
||||
/**
|
||||
* Returns whether the given key is the type key.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isTypeKey(String key);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,10 @@
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* A MongoWriter is responsible for converting an object of type T to the native MongoDB representation DBObject.
|
||||
@@ -37,4 +39,14 @@ public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
|
||||
* @return
|
||||
*/
|
||||
Object convertToMongoType(Object obj);
|
||||
|
||||
/**
|
||||
* Creates a {@link DBRef} to refer to the given object.
|
||||
*
|
||||
* @param object the object to create a {@link DBRef} to link to. The object's type has to carry an id attribute.
|
||||
* @param referingProperty the client-side property referring to the object which might carry additional metadata for
|
||||
* the {@link DBRef} object to create. Can be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
DBRef toDBRef(Object object, MongoPersistentProperty referingProperty);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -26,8 +26,10 @@ import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@@ -39,100 +41,132 @@ import com.mongodb.DBObject;
|
||||
*/
|
||||
public class QueryMapper {
|
||||
|
||||
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
|
||||
private static final String N_OR_PATTERN = "\\$.*or";
|
||||
|
||||
private final ConversionService conversionService;
|
||||
private final MongoConverter converter;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryMapper} with the given {@link ConversionService}.
|
||||
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
||||
*
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
*/
|
||||
public QueryMapper(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService);
|
||||
this.conversionService = conversionService;
|
||||
public QueryMapper(MongoConverter converter) {
|
||||
Assert.notNull(converter);
|
||||
this.conversionService = converter.getConversionService();
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
|
||||
* {@link PersistentEntity} metadata.
|
||||
*
|
||||
* @param query
|
||||
* @param entity
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entity can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
|
||||
|
||||
String idKey = null;
|
||||
|
||||
if (null != entity && entity.getIdProperty() != null) {
|
||||
idKey = entity.getIdProperty().getName();
|
||||
} else if (query.containsField("id")) {
|
||||
idKey = "id";
|
||||
} else if (query.containsField("_id")) {
|
||||
idKey = "_id";
|
||||
}
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
|
||||
for (String key : query.keySet()) {
|
||||
|
||||
String newKey = key;
|
||||
Object value = query.get(key);
|
||||
if (key.equals(idKey)) {
|
||||
|
||||
if (isIdKey(key, entity)) {
|
||||
if (value instanceof DBObject) {
|
||||
DBObject valueDbo = (DBObject) value;
|
||||
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Object[]) valueDbo.get(inKey)) {
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
||||
} else {
|
||||
value = getMappedObject((DBObject) value, entity);
|
||||
value = getMappedObject((DBObject) value, null);
|
||||
}
|
||||
} else {
|
||||
value = convertId(value);
|
||||
}
|
||||
newKey = "_id";
|
||||
} else if (key.startsWith("$") && key.endsWith("or")) {
|
||||
} else if (key.matches(N_OR_PATTERN)) {
|
||||
// $or/$nor
|
||||
BasicBSONList conditions = (BasicBSONList) value;
|
||||
Iterable<?> conditions = (Iterable<?>) value;
|
||||
BasicBSONList newConditions = new BasicBSONList();
|
||||
Iterator<Object> iter = conditions.iterator();
|
||||
Iterator<?> iter = conditions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
newConditions.add(getMappedObject((DBObject) iter.next(), entity));
|
||||
newConditions.add(getMappedObject((DBObject) iter.next(), null));
|
||||
}
|
||||
value = newConditions;
|
||||
} else if (key.equals("$ne")) {
|
||||
value = convertId(value);
|
||||
}
|
||||
|
||||
newDbo.put(newKey, value);
|
||||
|
||||
newDbo.put(newKey, convertSimpleOrDBObject(value, null));
|
||||
}
|
||||
|
||||
|
||||
return newDbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retriggers mapping if the given source is a {@link DBObject} or simply invokes the
|
||||
*
|
||||
* @param source
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (source instanceof BasicDBList) {
|
||||
return converter.convertToMongoType(source);
|
||||
}
|
||||
|
||||
if (source instanceof DBObject) {
|
||||
return getMappedObject((DBObject) source, entity);
|
||||
}
|
||||
|
||||
return converter.convertToMongoType(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given key will be considered an id key.
|
||||
*
|
||||
* @param key
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key);
|
||||
}
|
||||
|
||||
return DEFAULT_ID_NAMES.contains(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertId(Object id) {
|
||||
|
||||
for (Class<?> type : Arrays.asList(ObjectId.class, String.class)) {
|
||||
|
||||
if (id.getClass().isAssignableFrom(type)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
try {
|
||||
return conversionService.convert(id, type);
|
||||
} catch (ConversionException e) {
|
||||
// Ignore
|
||||
}
|
||||
try {
|
||||
return conversionService.convert(id, ObjectId.class);
|
||||
} catch (ConversionException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return id;
|
||||
return converter.convertToMongoType(id);
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class Box implements Shape {
|
||||
list.add(getUpperRight().asList());
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
|
||||
@@ -74,7 +74,7 @@ public class Box implements Shape {
|
||||
public String getCommand() {
|
||||
return "$box";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Box [%s, %s]", first, second);
|
||||
|
||||
@@ -40,10 +40,10 @@ public class Circle implements Shape {
|
||||
*/
|
||||
@PersistenceConstructor
|
||||
public Circle(Point center, double radius) {
|
||||
|
||||
|
||||
Assert.notNull(center);
|
||||
Assert.isTrue(radius >= 0, "Radius must not be negative!");
|
||||
|
||||
|
||||
this.center = center;
|
||||
this.radius = radius;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class Circle implements Shape {
|
||||
public double getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
|
||||
@@ -87,7 +87,7 @@ public class Circle implements Shape {
|
||||
result.add(getRadius());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
|
||||
@@ -104,26 +104,26 @@ public class Circle implements Shape {
|
||||
public String toString() {
|
||||
return String.format("Circle [center=%s, radius=%f]", center, radius);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Circle that = (Circle) obj;
|
||||
|
||||
|
||||
return this.center.equals(that.center) && this.radius == that.radius;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
|
||||
@@ -50,22 +50,22 @@ public class Polygon implements Shape, Iterable<Point> {
|
||||
this.points.addAll(Arrays.asList(x, y, z));
|
||||
this.points.addAll(Arrays.asList(others));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
|
||||
*/
|
||||
public List<List<Double>> asList() {
|
||||
|
||||
|
||||
List<List<Double>> result = new ArrayList<List<Double>>();
|
||||
|
||||
|
||||
for (Point point : points) {
|
||||
result.add(point.asList());
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
|
||||
@@ -73,7 +73,7 @@ public class Polygon implements Shape, Iterable<Point> {
|
||||
public String getCommand() {
|
||||
return "$polygon";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
@@ -88,20 +88,20 @@ public class Polygon implements Shape, Iterable<Point> {
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Polygon that = (Polygon) obj;
|
||||
|
||||
|
||||
return this.points.equals(that.points);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Common interface for all shapes. Allows building MongoDB representations of them.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface Shape {
|
||||
@@ -31,7 +31,7 @@ public interface Shape {
|
||||
* @return
|
||||
*/
|
||||
List<? extends Object> asList();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the command to be used to create the {@literal $within} criterion.
|
||||
*
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,9 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -24,14 +24,29 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Mark a class to use compound indexes.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CompoundIndex {
|
||||
|
||||
/**
|
||||
* The actual index definition in JSON format. The keys of the JSON document are the fields to be indexed, the values
|
||||
* define the index direction (1 for ascending, -1 for descending).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String def();
|
||||
|
||||
/**
|
||||
* It does not actually make sense to use that attribute as the direction has to be defined in the {@link #def()}
|
||||
* attribute actually.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
IndexDirection direction() default IndexDirection.ASCENDING;
|
||||
|
||||
boolean unique() default false;
|
||||
@@ -40,8 +55,18 @@ public @interface CompoundIndex {
|
||||
|
||||
boolean dropDups() default false;
|
||||
|
||||
/**
|
||||
* The name of the index to be created.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* The collection the index will be created in. Will default to the collection the annotated domain class will be
|
||||
* stored in.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String collection() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Value object for an index field.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public final class IndexField {
|
||||
|
||||
private final String key;
|
||||
private final Order order;
|
||||
private final boolean isGeo;
|
||||
|
||||
private IndexField(String key, Order order, boolean isGeo) {
|
||||
|
||||
Assert.hasText(key);
|
||||
Assert.isTrue(order != null ^ isGeo);
|
||||
|
||||
this.key = key;
|
||||
this.order = order;
|
||||
this.isGeo = isGeo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default {@link IndexField} with the given key and {@link Order}.
|
||||
*
|
||||
* @param key must not be {@literal null} or emtpy.
|
||||
* @param order must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static IndexField create(String key, Order order) {
|
||||
Assert.notNull(order);
|
||||
return new IndexField(key, order, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a geo {@link IndexField} for the given key.
|
||||
*
|
||||
* @param key must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public static IndexField geo(String key) {
|
||||
return new IndexField(key, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the order of the {@link IndexField} or {@literal null} in case we have a geo index field.
|
||||
*
|
||||
* @return the order
|
||||
*/
|
||||
public Order getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the {@link IndexField} is a geo index field.
|
||||
*
|
||||
* @return the isGeo
|
||||
*/
|
||||
public boolean isGeo() {
|
||||
return isGeo;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof IndexField)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexField that = (IndexField) obj;
|
||||
|
||||
return this.key.equals(that.key) && ObjectUtils.nullSafeEquals(this.order, that.order) && this.isGeo == that.isGeo;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
result += 31 * ObjectUtils.nullSafeHashCode(key);
|
||||
result += 31 * ObjectUtils.nullSafeHashCode(order);
|
||||
result += 31 * ObjectUtils.nullSafeHashCode(isGeo);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("IndexField [ key: %s, order: %s, isGeo: %s]", key, order, isGeo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
public class IndexInfo {
|
||||
|
||||
private final List<IndexField> indexFields;
|
||||
|
||||
private final String name;
|
||||
private final boolean unique;
|
||||
private final boolean dropDuplicates;
|
||||
private final boolean sparse;
|
||||
|
||||
public IndexInfo(List<IndexField> indexFields, String name, boolean unique, boolean dropDuplicates, boolean sparse) {
|
||||
|
||||
this.indexFields = Collections.unmodifiableList(indexFields);
|
||||
this.name = name;
|
||||
this.unique = unique;
|
||||
this.dropDuplicates = dropDuplicates;
|
||||
this.sparse = sparse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the individual index fields of the index.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<IndexField> getIndexFields() {
|
||||
return this.indexFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the index is covering exactly the fields given independently of the order.
|
||||
*
|
||||
* @param keys must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean isIndexForFields(Collection<String> keys) {
|
||||
|
||||
Assert.notNull(keys);
|
||||
List<String> indexKeys = new ArrayList<String>(indexFields.size());
|
||||
|
||||
for (IndexField field : indexFields) {
|
||||
indexKeys.add(field.getKey());
|
||||
}
|
||||
|
||||
return indexKeys.containsAll(keys);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public boolean isDropDuplicates() {
|
||||
return dropDuplicates;
|
||||
}
|
||||
|
||||
public boolean isSparse() {
|
||||
return sparse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IndexInfo [indexFields=" + indexFields + ", name=" + name + ", unique=" + unique + ", dropDuplicates="
|
||||
+ dropDuplicates + ", sparse=" + sparse + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (dropDuplicates ? 1231 : 1237);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(indexFields);
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + (sparse ? 1231 : 1237);
|
||||
result = prime * result + (unique ? 1231 : 1237);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
IndexInfo other = (IndexInfo) obj;
|
||||
if (dropDuplicates != other.dropDuplicates) {
|
||||
return false;
|
||||
}
|
||||
if (indexFields == null) {
|
||||
if (other.indexFields != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!indexFields.equals(other.indexFields)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
if (sparse != other.sparse) {
|
||||
return false;
|
||||
}
|
||||
if (unique != other.unique) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,12 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
/**
|
||||
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator when
|
||||
* MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
|
||||
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator
|
||||
* when MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
|
||||
*
|
||||
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
|
||||
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
||||
*
|
||||
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
|
||||
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class MongoMappingEventPublisher implements ApplicationEventPublisher {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,20 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
@@ -38,16 +37,16 @@ import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* Component that inspects {@link BasicMongoPersistentEntity} instances contained in the given
|
||||
* {@link MongoMappingContext} for indexing metadata and ensures the indexes to be available.
|
||||
* Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
|
||||
* for indexing metadata and ensures the indexes to be available.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoPersistentEntityIndexCreator implements
|
||||
ApplicationListener<MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty>> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MongoPersistentEntityIndexCreator.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(MongoPersistentEntityIndexCreator.class);
|
||||
|
||||
private final Map<Class<?>, Boolean> classesSeen = new ConcurrentHashMap<Class<?>, Boolean>();
|
||||
private final MongoDbFactory mongoDbFactory;
|
||||
@@ -76,7 +75,13 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
*/
|
||||
public void onApplicationEvent(
|
||||
MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty> event) {
|
||||
checkForIndexes(event.getPersistentEntity());
|
||||
|
||||
PersistentEntity<?, ?> entity = event.getPersistentEntity();
|
||||
|
||||
// Double check type as Spring infrastructure does not consider nested generics
|
||||
if (entity instanceof MongoPersistentEntity) {
|
||||
checkForIndexes(event.getPersistentEntity());
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkForIndexes(final MongoPersistentEntity<?> entity) {
|
||||
@@ -90,12 +95,12 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
if (type.isAnnotationPresent(CompoundIndexes.class)) {
|
||||
CompoundIndexes indexes = type.getAnnotation(CompoundIndexes.class);
|
||||
for (CompoundIndex index : indexes.value()) {
|
||||
String indexColl = index.collection();
|
||||
if ("".equals(indexColl)) {
|
||||
indexColl = entity.getCollection();
|
||||
}
|
||||
ensureIndex(indexColl, index.name(), index.def(), index.direction(), index.unique(), index.dropDups(),
|
||||
index.sparse());
|
||||
|
||||
String indexColl = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
|
||||
DBObject definition = (DBObject) JSON.parse(index.def());
|
||||
|
||||
ensureIndex(indexColl, index.name(), definition, index.unique(), index.dropDups(), index.sparse());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Created compound index " + index);
|
||||
}
|
||||
@@ -104,10 +109,14 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) {
|
||||
|
||||
Field field = persistentProperty.getField();
|
||||
|
||||
if (field.isAnnotationPresent(Indexed.class)) {
|
||||
|
||||
Indexed index = field.getAnnotation(Indexed.class);
|
||||
String name = index.name();
|
||||
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = persistentProperty.getFieldName();
|
||||
} else {
|
||||
@@ -119,11 +128,17 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
|
||||
ensureIndex(collection, name, null, index.direction(), index.unique(), index.dropDups(), index.sparse());
|
||||
int direction = index.direction() == IndexDirection.ASCENDING ? 1 : -1;
|
||||
DBObject definition = new BasicDBObject(persistentProperty.getFieldName(), direction);
|
||||
|
||||
ensureIndex(collection, name, definition, index.unique(), index.dropDups(), index.sparse());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Created property index " + index);
|
||||
}
|
||||
|
||||
} else if (field.isAnnotationPresent(GeoSpatialIndexed.class)) {
|
||||
|
||||
GeoSpatialIndexed index = field.getAnnotation(GeoSpatialIndexed.class);
|
||||
@@ -148,21 +163,15 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureIndex(String collection, final String name, final String def, final IndexDirection direction,
|
||||
final boolean unique, final boolean dropDups, final boolean sparse) {
|
||||
DBObject defObj;
|
||||
if (null != def) {
|
||||
defObj = (DBObject) JSON.parse(def);
|
||||
} else {
|
||||
defObj = new BasicDBObject();
|
||||
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
|
||||
}
|
||||
protected void ensureIndex(String collection, String name, DBObject indexDefinition, boolean unique,
|
||||
boolean dropDups, boolean sparse) {
|
||||
|
||||
DBObject opts = new BasicDBObject();
|
||||
opts.put("name", name);
|
||||
opts.put("dropDups", dropDups);
|
||||
opts.put("sparse", sparse);
|
||||
opts.put("unique", unique);
|
||||
mongoDbFactory.getDb().getCollection(collection).ensureIndex(defObj, opts);
|
||||
}
|
||||
|
||||
mongoDbFactory.getDb().getCollection(collection).ensureIndex(indexDefinition, opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
@@ -39,7 +39,7 @@ import com.mongodb.DBObject;
|
||||
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements
|
||||
MongoPersistentProperty {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(BasicMongoPersistentProperty.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BasicMongoPersistentProperty.class);
|
||||
|
||||
private static final String ID_FIELD_NAME = "_id";
|
||||
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
|
||||
@@ -87,6 +87,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
if (super.isIdProperty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty {
|
||||
|
||||
private Boolean isIdProperty;
|
||||
private Boolean isAssociation;
|
||||
private String fieldName;
|
||||
|
||||
/**
|
||||
@@ -53,10 +54,22 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty
|
||||
if (this.isIdProperty == null) {
|
||||
this.isIdProperty = super.isIdProperty();
|
||||
}
|
||||
|
||||
|
||||
return this.isIdProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty#isAssociation()
|
||||
*/
|
||||
@Override
|
||||
public boolean isAssociation() {
|
||||
if (this.isAssociation == null) {
|
||||
this.isAssociation = super.isAssociation();
|
||||
}
|
||||
return this.isAssociation;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty#getFieldName()
|
||||
@@ -67,7 +80,7 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty
|
||||
if (this.fieldName == null) {
|
||||
this.fieldName = super.getFieldName();
|
||||
}
|
||||
|
||||
return super.getFieldName();
|
||||
|
||||
return this.fieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,9 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -24,19 +24,21 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.data.annotation.Reference;
|
||||
|
||||
/**
|
||||
* An annotation that indicates the annotated field is to be stored using a com.mongodb.DBRef
|
||||
* An annotation that indicates the annotated field is to be stored using a {@link com.mongodb.DBRef}.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @authot Oliver Gierke
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD })
|
||||
@Reference
|
||||
public @interface DBRef {
|
||||
|
||||
String collection() default "";
|
||||
|
||||
String id() default "";
|
||||
|
||||
/**
|
||||
* The database the referred entity resides in.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String db() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ import org.springframework.data.util.TypeInformation;
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke ogierke@vmware.com
|
||||
*/
|
||||
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty> implements ApplicationContextAware {
|
||||
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@@ -57,16 +58,16 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
||||
*/
|
||||
@Override
|
||||
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
|
||||
BasicMongoPersistentEntity<T> entity = new BasicMongoPersistentEntity<T>(typeInformation);
|
||||
|
||||
|
||||
if (context != null) {
|
||||
entity.setApplicationContext(context);
|
||||
}
|
||||
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
|
||||
@@ -19,11 +19,15 @@ import java.math.BigInteger;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.types.Binary;
|
||||
import org.bson.types.CodeWScope;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
@@ -33,19 +37,23 @@ import com.mongodb.DBRef;
|
||||
*/
|
||||
public abstract class MongoSimpleTypes {
|
||||
|
||||
public static final Set<Class<?>> SUPPORTED_ID_CLASSES;
|
||||
|
||||
public static final Set<Class<?>> AUTOGENERATED_ID_TYPES;
|
||||
|
||||
static {
|
||||
Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||
classes.add(ObjectId.class);
|
||||
classes.add(String.class);
|
||||
classes.add(BigInteger.class);
|
||||
SUPPORTED_ID_CLASSES = Collections.unmodifiableSet(classes);
|
||||
AUTOGENERATED_ID_TYPES = Collections.unmodifiableSet(classes);
|
||||
|
||||
Set<Class<?>> simpleTypes = new HashSet<Class<?>>();
|
||||
simpleTypes.add(DBRef.class);
|
||||
simpleTypes.add(ObjectId.class);
|
||||
simpleTypes.add(CodeWScope.class);
|
||||
simpleTypes.add(DBObject.class);
|
||||
simpleTypes.add(Pattern.class);
|
||||
simpleTypes.add(Binary.class);
|
||||
simpleTypes.add(UUID.class);
|
||||
MONGO_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base class to implement domain class specific {@link ApplicationListener}s.
|
||||
*
|
||||
@@ -29,14 +30,15 @@ import org.springframework.core.GenericTypeResolver;
|
||||
*/
|
||||
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
||||
|
||||
protected final Log LOG = LogFactory.getLog(getClass());
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractMongoEventListener.class);
|
||||
private final Class<?> domainClass;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractMongoEventListener}.
|
||||
*/
|
||||
public AbstractMongoEventListener() {
|
||||
this.domainClass = GenericTypeResolver.resolveTypeArgument(this.getClass(), AbstractMongoEventListener.class);
|
||||
Class<?> typeArgument = GenericTypeResolver.resolveTypeArgument(this.getClass(), AbstractMongoEventListener.class);
|
||||
this.domainClass = typeArgument == null ? Object.class : typeArgument;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -39,9 +39,9 @@ public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
* @param type must not be {@literal null}.
|
||||
*/
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
||||
|
||||
|
||||
super(dbo, dbo);
|
||||
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -15,22 +15,31 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
|
||||
private Log log = LogFactory.getLog(getClass());
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggingEventListener.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeConvert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeConvert(Object source) {
|
||||
log.info("onBeforeConvert: " + source);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeSave(java.lang.Object, com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
try {
|
||||
@@ -39,19 +48,30 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onAfterSave(java.lang.Object, com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
log.info("onAfterSave: " + source + ", " + dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onAfterLoad(com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
log.info("onAfterLoad: " + dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onAfterConvert(com.mongodb.DBObject, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
log.info("onAfterConvert: " + dbo + ", " + source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.Validator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* javax.validation dependant entities validator. When it is registered as Spring component its automatically invoked
|
||||
* before entities are saved in database.
|
||||
*
|
||||
* @author Maciej Walkowiak
|
||||
*/
|
||||
public class ValidatingMongoEventListener extends AbstractMongoEventListener<Object> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ValidatingMongoEventListener.class);
|
||||
|
||||
private final Validator validator;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ValidatingMongoEventListener} using the given {@link Validator}.
|
||||
*
|
||||
* @param validator must not be {@literal null}.
|
||||
*/
|
||||
public ValidatingMongoEventListener(Validator validator) {
|
||||
Assert.notNull(validator);
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeSave(java.lang.Object, com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
|
||||
LOG.debug("Validating object: {}", source);
|
||||
Set violations = validator.validate(source);
|
||||
|
||||
if (!violations.isEmpty()) {
|
||||
|
||||
LOG.info("During object: {} validation violations found: {}", source, violations);
|
||||
throw new ConstraintViolationException(violations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapreduce;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Collects the parameters required to perform a group operation on a collection. The query condition and the input
|
||||
* collection are specified on the group method as method arguments to be consistent with other operations, e.g.
|
||||
* map-reduce.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class GroupBy {
|
||||
|
||||
private DBObject dboKeys;
|
||||
private String keyFunction;
|
||||
private String initial;
|
||||
private DBObject initialDbObject;
|
||||
private String reduce;
|
||||
private String finalize;
|
||||
|
||||
public GroupBy(String... keys) {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
for (String key : keys) {
|
||||
dbo.put(key, 1);
|
||||
}
|
||||
dboKeys = dbo;
|
||||
}
|
||||
|
||||
// NOTE GroupByCommand does not handle keyfunction.
|
||||
|
||||
public GroupBy(String key, boolean isKeyFunction) {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
if (isKeyFunction) {
|
||||
keyFunction = key;
|
||||
} else {
|
||||
dbo.put(key, 1);
|
||||
dboKeys = dbo;
|
||||
}
|
||||
}
|
||||
|
||||
public static GroupBy keyFunction(String key) {
|
||||
return new GroupBy(key, true);
|
||||
}
|
||||
|
||||
public static GroupBy key(String... keys) {
|
||||
return new GroupBy(keys);
|
||||
}
|
||||
|
||||
public GroupBy initialDocument(String initialDocument) {
|
||||
initial = initialDocument;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupBy initialDocument(DBObject initialDocument) {
|
||||
initialDbObject = initialDocument;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupBy reduceFunction(String reduceFunction) {
|
||||
reduce = reduceFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroupBy finalizeFunction(String finalizeFunction) {
|
||||
finalize = finalizeFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DBObject getGroupByObject() {
|
||||
// return new GroupCommand(dbCollection, dboKeys, condition, initial, reduce, finalize);
|
||||
BasicDBObject dbo = new BasicDBObject();
|
||||
if (dboKeys != null) {
|
||||
dbo.put("key", dboKeys);
|
||||
}
|
||||
if (keyFunction != null) {
|
||||
dbo.put("$keyf", keyFunction);
|
||||
}
|
||||
|
||||
dbo.put("$reduce", reduce);
|
||||
|
||||
dbo.put("initial", initialDbObject);
|
||||
if (initial != null) {
|
||||
dbo.put("initial", initial);
|
||||
}
|
||||
if (finalize != null) {
|
||||
dbo.put("finalize", finalize);
|
||||
}
|
||||
return dbo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapreduce;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Collects the results of executing a group operation.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @param <T> The class in which the results are mapped onto, accessible via an interator.
|
||||
*/
|
||||
public class GroupByResults<T> implements Iterable<T> {
|
||||
|
||||
private final List<T> mappedResults;
|
||||
private final DBObject rawResults;
|
||||
|
||||
private double count;
|
||||
private int keys;
|
||||
private String serverUsed;
|
||||
|
||||
public GroupByResults(List<T> mappedResults, DBObject rawResults) {
|
||||
Assert.notNull(mappedResults);
|
||||
Assert.notNull(rawResults);
|
||||
this.mappedResults = mappedResults;
|
||||
this.rawResults = rawResults;
|
||||
parseKeys();
|
||||
parseCount();
|
||||
parseServerUsed();
|
||||
}
|
||||
|
||||
public double getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public String getServerUsed() {
|
||||
return serverUsed;
|
||||
}
|
||||
|
||||
public Iterator<T> iterator() {
|
||||
return mappedResults.iterator();
|
||||
}
|
||||
|
||||
public DBObject getRawResults() {
|
||||
return rawResults;
|
||||
}
|
||||
|
||||
private void parseCount() {
|
||||
Object object = rawResults.get("count");
|
||||
if (object instanceof Double) {
|
||||
count = (Double) object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void parseKeys() {
|
||||
Object object = rawResults.get("keys");
|
||||
if (object instanceof Integer) {
|
||||
keys = (Integer) object;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseServerUsed() {
|
||||
// "serverUsed" : "127.0.0.1:27017"
|
||||
Object object = rawResults.get("serverUsed");
|
||||
if (object instanceof String) {
|
||||
serverUsed = (String) object;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,14 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapreduce;
|
||||
|
||||
/**
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class MapReduceCounts {
|
||||
|
||||
private int inputCount;
|
||||
|
||||
private int emitCount;
|
||||
|
||||
private int outputCount;
|
||||
private final int inputCount;
|
||||
private final int emitCount;
|
||||
private final int outputCount;
|
||||
|
||||
public MapReduceCounts(int inputCount, int emitCount, int outputCount) {
|
||||
super();
|
||||
@@ -42,12 +43,20 @@ public class MapReduceCounts {
|
||||
return outputCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MapReduceCounts [inputCount=" + inputCount + ", emitCount=" + emitCount + ", outputCount=" + outputCount
|
||||
+ "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
@@ -58,24 +67,31 @@ public class MapReduceCounts {
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
if (this == obj) {
|
||||
return true;
|
||||
if (obj == null)
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MapReduceCounts other = (MapReduceCounts) obj;
|
||||
if (emitCount != other.emitCount)
|
||||
if (emitCount != other.emitCount) {
|
||||
return false;
|
||||
if (inputCount != other.inputCount)
|
||||
}
|
||||
if (inputCount != other.inputCount) {
|
||||
return false;
|
||||
if (outputCount != other.outputCount)
|
||||
}
|
||||
if (outputCount != other.outputCount) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -39,15 +39,13 @@ public class MapReduceOptions {
|
||||
private Boolean jsMode;
|
||||
|
||||
private Boolean verbose = true;
|
||||
|
||||
|
||||
private Map<String, Object> extraOptions = new HashMap<String, Object>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided key
|
||||
* Static factory method to create a MapReduceOptions instance
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
* @return a new instance
|
||||
*/
|
||||
public static MapReduceOptions options() {
|
||||
return new MapReduceOptions();
|
||||
@@ -190,12 +188,12 @@ public class MapReduceOptions {
|
||||
this.verbose = verbose;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add additional extra options that may not have a method on this class. This method will help if you use a
|
||||
* version of this client library with a server version that has added additional map-reduce options that do not
|
||||
* yet have an method for use in setting them.
|
||||
* options
|
||||
* Add additional extra options that may not have a method on this class. This method will help if you use a version
|
||||
* of this client library with a server version that has added additional map-reduce options that do not yet have an
|
||||
* method for use in setting them. options
|
||||
*
|
||||
* @param key The key option
|
||||
* @param value The value of the option
|
||||
* @return MapReduceOptions so that methods can be chained in a fluent API style
|
||||
@@ -204,40 +202,39 @@ public class MapReduceOptions {
|
||||
extraOptions.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getExtraOptions() {
|
||||
return extraOptions;
|
||||
return extraOptions;
|
||||
}
|
||||
|
||||
|
||||
public String getFinalizeFunction() {
|
||||
return this.finalizeFunction;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getJavaScriptMode() {
|
||||
return this.jsMode;
|
||||
}
|
||||
|
||||
|
||||
public String getOutputCollection() {
|
||||
return this.outputCollection;
|
||||
}
|
||||
|
||||
|
||||
public String getOutputDatabase() {
|
||||
return this.outputDatabase;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getOutputSharded() {
|
||||
return this.outputSharded;
|
||||
}
|
||||
|
||||
|
||||
public MapReduceCommand.OutputType getOutputType() {
|
||||
return this.outputType;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getScopeVariables() {
|
||||
return this.scopeVariables;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DBObject getOptionsObject() {
|
||||
BasicDBObject cmd = new BasicDBObject();
|
||||
|
||||
@@ -254,7 +251,7 @@ public class MapReduceOptions {
|
||||
if (scopeVariables != null) {
|
||||
cmd.put("scope", scopeVariables);
|
||||
}
|
||||
|
||||
|
||||
if (!extraOptions.keySet().isEmpty()) {
|
||||
cmd.putAll(extraOptions);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,73 +22,128 @@ import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Collects the results of performing a MapReduce operations.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
* @param <T> The class in which the results are mapped onto, accessible via an iterator.
|
||||
*/
|
||||
public class MapReduceResults<T> implements Iterable<T> {
|
||||
|
||||
private final List<T> mappedResults;
|
||||
|
||||
private DBObject rawResults;
|
||||
private final DBObject rawResults;
|
||||
private final String outputCollection;
|
||||
private final MapReduceTiming mapReduceTiming;
|
||||
private final MapReduceCounts mapReduceCounts;
|
||||
|
||||
private MapReduceTiming mapReduceTiming;
|
||||
|
||||
private MapReduceCounts mapReduceCounts;
|
||||
|
||||
private String outputCollection;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MapReduceResults} from the given mapped results and the raw one.
|
||||
*
|
||||
* @param mappedResults must not be {@literal null}.
|
||||
* @param rawResults must not be {@literal null}.
|
||||
*/
|
||||
public MapReduceResults(List<T> mappedResults, DBObject rawResults) {
|
||||
|
||||
Assert.notNull(mappedResults);
|
||||
Assert.notNull(rawResults);
|
||||
|
||||
this.mappedResults = mappedResults;
|
||||
this.rawResults = rawResults;
|
||||
parseTiming(rawResults);
|
||||
parseCounts(rawResults);
|
||||
if (rawResults.get("result") != null) {
|
||||
this.outputCollection = (String) rawResults.get("result");
|
||||
}
|
||||
this.mapReduceTiming = parseTiming(rawResults);
|
||||
this.mapReduceCounts = parseCounts(rawResults);
|
||||
this.outputCollection = parseOutputCollection(rawResults);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
public Iterator<T> iterator() {
|
||||
return mappedResults.iterator();
|
||||
return mappedResults.iterator();
|
||||
}
|
||||
|
||||
|
||||
public MapReduceTiming getTiming() {
|
||||
return mapReduceTiming;
|
||||
}
|
||||
|
||||
|
||||
public MapReduceCounts getCounts() {
|
||||
return mapReduceCounts;
|
||||
}
|
||||
|
||||
|
||||
public String getOutputCollection() {
|
||||
return outputCollection;
|
||||
}
|
||||
|
||||
|
||||
public DBObject getRawResults() {
|
||||
return rawResults;
|
||||
}
|
||||
|
||||
protected void parseTiming(DBObject rawResults) {
|
||||
|
||||
private MapReduceTiming parseTiming(DBObject rawResults) {
|
||||
|
||||
DBObject timing = (DBObject) rawResults.get("timing");
|
||||
if (timing != null) {
|
||||
if (timing.get("mapTime") != null && timing.get("emitLoop") != null && timing.get("total") != null) {
|
||||
mapReduceTiming = new MapReduceTiming( (Long)timing.get("mapTime"),
|
||||
(Integer)timing.get("emitLoop"),
|
||||
(Integer)timing.get("total"));
|
||||
}
|
||||
} else {
|
||||
mapReduceTiming = new MapReduceTiming(-1,-1,-1);
|
||||
|
||||
if (timing == null) {
|
||||
return new MapReduceTiming(-1, -1, -1);
|
||||
}
|
||||
|
||||
if (timing.get("mapTime") != null && timing.get("emitLoop") != null && timing.get("total") != null) {
|
||||
return new MapReduceTiming(getAsLong(timing, "mapTime"), getAsLong(timing, "emitLoop"),
|
||||
getAsLong(timing, "total"));
|
||||
}
|
||||
|
||||
return new MapReduceTiming(-1, -1, -1);
|
||||
}
|
||||
|
||||
|
||||
protected void parseCounts(DBObject rawResults) {
|
||||
|
||||
/**
|
||||
* Returns the value of the source's field with the given key as {@link Long}.
|
||||
*
|
||||
* @param source
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
private Long getAsLong(DBObject source, String key) {
|
||||
Object raw = source.get(key);
|
||||
return raw instanceof Long ? (Long) raw : (Integer) raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the raw {@link DBObject} result into a {@link MapReduceCounts} value object.
|
||||
*
|
||||
* @param rawResults
|
||||
* @return
|
||||
*/
|
||||
private MapReduceCounts parseCounts(DBObject rawResults) {
|
||||
|
||||
DBObject counts = (DBObject) rawResults.get("counts");
|
||||
if (counts != null) {
|
||||
if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) {
|
||||
mapReduceCounts = new MapReduceCounts( (Integer)counts.get("input"), (Integer)counts.get("emit"), (Integer)counts.get("output"));
|
||||
}
|
||||
} else {
|
||||
mapReduceCounts = new MapReduceCounts(-1,-1,-1);
|
||||
|
||||
if (counts == null) {
|
||||
return new MapReduceCounts(-1, -1, -1);
|
||||
}
|
||||
|
||||
if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) {
|
||||
return new MapReduceCounts((Integer) counts.get("input"), (Integer) counts.get("emit"),
|
||||
(Integer) counts.get("output"));
|
||||
}
|
||||
|
||||
return new MapReduceCounts(-1, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the output collection from the raw {@link DBObject} result.
|
||||
*
|
||||
* @param rawResults
|
||||
* @return
|
||||
*/
|
||||
private String parseOutputCollection(DBObject rawResults) {
|
||||
|
||||
Object resultField = rawResults.get("result");
|
||||
|
||||
if (resultField == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resultField instanceof DBObject ? ((DBObject) resultField).get("collection").toString() : resultField
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ package org.springframework.data.mongodb.core.mapreduce;
|
||||
public class MapReduceTiming {
|
||||
|
||||
private long mapTime;
|
||||
|
||||
|
||||
private long emitLoopTime;
|
||||
|
||||
|
||||
private long totalTime;
|
||||
|
||||
|
||||
public MapReduceTiming(long mapTime, long emitLoopTime, long totalTime) {
|
||||
this.mapTime = mapTime;
|
||||
this.emitLoopTime = emitLoopTime;
|
||||
this.totalTime = totalTime;
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public long getMapTime() {
|
||||
@@ -73,8 +73,5 @@ public class MapReduceTiming {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,18 +15,23 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.bson.types.BasicBSONList;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.core.geo.Circle;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.geo.Shape;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -68,7 +73,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided key
|
||||
*
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@@ -78,7 +83,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided key
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Criteria and(String key) {
|
||||
@@ -87,7 +92,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using equality
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -96,16 +101,20 @@ public class Criteria implements CriteriaDefinition {
|
||||
throw new InvalidMongoDbApiUsageException(
|
||||
"Multiple 'is' values declared. You need to use 'and' with multiple criteria");
|
||||
}
|
||||
if (this.criteria.size() > 0 && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1])) {
|
||||
if (lastOperatorWasNot()) {
|
||||
throw new InvalidMongoDbApiUsageException("Invalid query: 'not' can't be used with 'is' - use 'ne' instead.");
|
||||
}
|
||||
this.isValue = o;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean lastOperatorWasNot() {
|
||||
return this.criteria.size() > 0 && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $ne operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -116,7 +125,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $lt operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -127,7 +136,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $lte operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -138,7 +147,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $gt operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -149,7 +158,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $gte operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@@ -160,7 +169,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $in operator
|
||||
*
|
||||
*
|
||||
* @param o the values to match against
|
||||
* @return
|
||||
*/
|
||||
@@ -169,35 +178,39 @@ public class Criteria implements CriteriaDefinition {
|
||||
throw new InvalidMongoDbApiUsageException("You can only pass in one argument of type "
|
||||
+ o[1].getClass().getName());
|
||||
}
|
||||
criteria.put("$in", o);
|
||||
criteria.put("$in", Arrays.asList(o));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $in operator
|
||||
*
|
||||
*
|
||||
* @param c the collection containing the values to match against
|
||||
* @return
|
||||
*/
|
||||
public Criteria in(Collection<?> c) {
|
||||
criteria.put("$in", c.toArray());
|
||||
criteria.put("$in", c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $nin operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
public Criteria nin(Object... o) {
|
||||
return nin(Arrays.asList(o));
|
||||
}
|
||||
|
||||
public Criteria nin(Collection<?> o) {
|
||||
criteria.put("$nin", o);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $mod operator
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
* @param remainder
|
||||
* @return
|
||||
@@ -212,18 +225,22 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $all operator
|
||||
*
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
public Criteria all(Object... o) {
|
||||
return all(Arrays.asList(o));
|
||||
}
|
||||
|
||||
public Criteria all(Collection<?> o) {
|
||||
criteria.put("$all", o);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $size operator
|
||||
*
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
@@ -234,7 +251,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $exists operator
|
||||
*
|
||||
*
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
@@ -245,7 +262,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $type operator
|
||||
*
|
||||
*
|
||||
* @param t
|
||||
* @return
|
||||
*/
|
||||
@@ -256,43 +273,65 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $not meta operator which affects the clause directly following
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Criteria not() {
|
||||
criteria.put("$not", null);
|
||||
return not(null);
|
||||
}
|
||||
|
||||
private Criteria not(Object value) {
|
||||
criteria.put("$not", value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using a $regex
|
||||
*
|
||||
*
|
||||
* @param re
|
||||
* @return
|
||||
*/
|
||||
public Criteria regex(String re) {
|
||||
criteria.put("$regex", re);
|
||||
return this;
|
||||
return regex(re, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using a $regex and $options
|
||||
*
|
||||
*
|
||||
* @param re
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
public Criteria regex(String re, String options) {
|
||||
criteria.put("$regex", re);
|
||||
if (StringUtils.hasText(options)) {
|
||||
criteria.put("$options", options);
|
||||
return regex(toPattern(re, options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntactical sugar for {@link #is(Object)} making obvious that we create a regex predicate.
|
||||
*
|
||||
* @param pattern
|
||||
* @return
|
||||
*/
|
||||
public Criteria regex(Pattern pattern) {
|
||||
|
||||
Assert.notNull(pattern);
|
||||
|
||||
if (lastOperatorWasNot()) {
|
||||
return not(pattern);
|
||||
}
|
||||
|
||||
this.isValue = pattern;
|
||||
return this;
|
||||
}
|
||||
|
||||
private Pattern toPattern(String regex, String options) {
|
||||
Assert.notNull(regex);
|
||||
return Pattern.compile(regex, options == null ? 0 : BSON.regexFlags(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
|
||||
*
|
||||
*
|
||||
* @param circle must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
@@ -311,7 +350,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a geospatial criterion using a $near operation
|
||||
*
|
||||
*
|
||||
* @param point must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
@@ -323,7 +362,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and higher.
|
||||
*
|
||||
*
|
||||
* @param point must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
@@ -335,7 +374,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a geospatical criterion using a $maxDistance operation, for use with $near
|
||||
*
|
||||
*
|
||||
* @param maxDistance
|
||||
* @return
|
||||
*/
|
||||
@@ -346,7 +385,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $elemMatch operator
|
||||
*
|
||||
*
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
@@ -357,7 +396,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates an 'or' criteria using the $or operator for all of the provided criteria
|
||||
*
|
||||
*
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria orOperator(Criteria... criteria) {
|
||||
@@ -368,7 +407,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates a 'nor' criteria using the $nor operator for all of the provided criteria
|
||||
*
|
||||
*
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria norOperator(Criteria... criteria) {
|
||||
@@ -379,7 +418,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Creates an 'and' criteria using the $and operator for all of the provided criteria
|
||||
*
|
||||
*
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria andOperator(Criteria... criteria) {
|
||||
@@ -388,17 +427,14 @@ public class Criteria implements CriteriaDefinition {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.datastore.document.mongodb.query.Criteria#
|
||||
* getCriteriaObject(java.lang.String)
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.query.CriteriaDefinition#getCriteriaObject()
|
||||
*/
|
||||
public DBObject getCriteriaObject() {
|
||||
if (this.criteriaChain.size() == 1) {
|
||||
return criteriaChain.get(0).getSingleCriteriaObject();
|
||||
@@ -418,16 +454,17 @@ public class Criteria implements CriteriaDefinition {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
boolean not = false;
|
||||
for (String k : this.criteria.keySet()) {
|
||||
Object value = this.criteria.get(k);
|
||||
if (not) {
|
||||
DBObject notDbo = new BasicDBObject();
|
||||
notDbo.put(k, this.criteria.get(k));
|
||||
notDbo.put(k, value);
|
||||
dbo.put("$not", notDbo);
|
||||
not = false;
|
||||
} else {
|
||||
if ("$not".equals(k)) {
|
||||
if ("$not".equals(k) && value == null) {
|
||||
not = true;
|
||||
} else {
|
||||
dbo.put(k, this.criteria.get(k));
|
||||
dbo.put(k, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,12 +490,70 @@ public class Criteria implements CriteriaDefinition {
|
||||
Object existing = dbo.get(key);
|
||||
if (existing == null) {
|
||||
dbo.put(key, value);
|
||||
}
|
||||
else {
|
||||
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, " +
|
||||
"you can't add a second '" + key + "' expression specified as '" + key + " : " + value + "'. " +
|
||||
"Criteria already contains '" + key + " : " + existing + "'.");
|
||||
} else {
|
||||
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, "
|
||||
+ "you can't add a second '" + key + "' expression specified as '" + key + " : " + value + "'. "
|
||||
+ "Criteria already contains '" + key + " : " + existing + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Criteria that = (Criteria) obj;
|
||||
|
||||
boolean keyEqual = this.key == null ? that.key == null : this.key.equals(that.key);
|
||||
boolean criteriaEqual = this.criteria.equals(that.criteria);
|
||||
boolean valueEqual = isEqual(this.isValue, that.isValue);
|
||||
|
||||
return keyEqual && criteriaEqual && valueEqual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given objects for equality. Handles {@link Pattern} and arrays correctly.
|
||||
*
|
||||
* @param left
|
||||
* @param right
|
||||
* @return
|
||||
*/
|
||||
private boolean isEqual(Object left, Object right) {
|
||||
|
||||
if (left == null) {
|
||||
return right == null;
|
||||
}
|
||||
|
||||
if (left instanceof Pattern) {
|
||||
return right instanceof Pattern ? ((Pattern) left).pattern().equals(((Pattern) right).pattern()) : false;
|
||||
}
|
||||
|
||||
return ObjectUtils.nullSafeEquals(left, right);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += nullSafeHashCode(key);
|
||||
result += criteria.hashCode();
|
||||
result += nullSafeHashCode(isValue);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.springframework.data.mongodb.core.SerializationUtils.*;
|
||||
import static org.springframework.util.ObjectUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
|
||||
public class Query {
|
||||
|
||||
@@ -30,10 +35,11 @@ public class Query {
|
||||
private Sort sort;
|
||||
private int skip;
|
||||
private int limit;
|
||||
private String hint;
|
||||
|
||||
/**
|
||||
* Static factory method to create a Query using the provided criteria
|
||||
*
|
||||
*
|
||||
* @param critera
|
||||
* @return
|
||||
*/
|
||||
@@ -53,20 +59,17 @@ public class Query {
|
||||
String key = criteria.getKey();
|
||||
if (existing == null) {
|
||||
this.criteria.put(key, criteria);
|
||||
}
|
||||
else {
|
||||
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, " +
|
||||
"you can't add a second '" + key + "' criteria. " +
|
||||
"Query already contains '" + existing.getCriteriaObject() + "'.");
|
||||
} else {
|
||||
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, "
|
||||
+ "you can't add a second '" + key + "' criteria. " + "Query already contains '"
|
||||
+ existing.getCriteriaObject() + "'.");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Field fields() {
|
||||
synchronized (this) {
|
||||
if (fieldSpec == null) {
|
||||
this.fieldSpec = new Field();
|
||||
}
|
||||
if (fieldSpec == null) {
|
||||
this.fieldSpec = new Field();
|
||||
}
|
||||
return this.fieldSpec;
|
||||
}
|
||||
@@ -81,12 +84,23 @@ public class Query {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the query to use the given hint when being executed.
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public Query withHint(String name) {
|
||||
Assert.hasText(name, "Hint must not be empty or null!");
|
||||
this.hint = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sort sort() {
|
||||
synchronized (this) {
|
||||
if (this.sort == null) {
|
||||
this.sort = new Sort();
|
||||
}
|
||||
if (this.sort == null) {
|
||||
this.sort = new Sort();
|
||||
}
|
||||
|
||||
return this.sort;
|
||||
}
|
||||
|
||||
@@ -122,7 +136,67 @@ public class Query {
|
||||
return this.limit;
|
||||
}
|
||||
|
||||
public String getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
protected List<Criteria> getCriteria() {
|
||||
return new ArrayList<Criteria>(this.criteria.values());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Query: %s, Fields: %s, Sort: %s", serializeToJsonSafely(getQueryObject()),
|
||||
serializeToJsonSafely(getFieldsObject()), serializeToJsonSafely(getSortObject()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Query that = (Query) obj;
|
||||
|
||||
boolean criteriaEqual = this.criteria.equals(that.criteria);
|
||||
boolean fieldsEqual = this.fieldSpec == null ? that.fieldSpec == null : this.fieldSpec.equals(that.fieldSpec);
|
||||
boolean sortEqual = this.sort == null ? that.sort == null : this.sort.equals(that.sort);
|
||||
boolean hintEqual = this.hint == null ? that.hint == null : this.hint.equals(that.hint);
|
||||
boolean skipEqual = this.skip == that.skip;
|
||||
boolean limitEqual = this.limit == that.limit;
|
||||
|
||||
return criteriaEqual && fieldsEqual && sortEqual && hintEqual && skipEqual && limitEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += 31 * criteria.hashCode();
|
||||
result += 31 * nullSafeHashCode(fieldSpec);
|
||||
result += 31 * nullSafeHashCode(sort);
|
||||
result += 31 * nullSafeHashCode(hint);
|
||||
result += 31 * skip;
|
||||
result += 31 * limit;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.gridfs;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to abstract Ant paths.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class AntPath {
|
||||
|
||||
private static final String PREFIX_DELIMITER = ":";
|
||||
private static final Pattern WILDCARD_PATTERN = Pattern.compile("\\?|\\*\\*|\\*");
|
||||
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AntPath} from the given path.
|
||||
*
|
||||
* @param path must not be {@literal null}.
|
||||
*/
|
||||
public AntPath(String path) {
|
||||
Assert.notNull(path);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the path is a pattern.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPattern() {
|
||||
String path = stripPrefix(this.path);
|
||||
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
|
||||
}
|
||||
|
||||
private static String stripPrefix(String path) {
|
||||
int index = path.indexOf(PREFIX_DELIMITER);
|
||||
return (index > -1 ? path.substring(index + 1) : path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the regular expression equivalent of this Ant path.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String toRegex() {
|
||||
|
||||
StringBuilder patternBuilder = new StringBuilder();
|
||||
Matcher m = WILDCARD_PATTERN.matcher(path);
|
||||
int end = 0;
|
||||
|
||||
while (m.find()) {
|
||||
|
||||
patternBuilder.append(quote(path, end, m.start()));
|
||||
String match = m.group();
|
||||
|
||||
if ("?".equals(match)) {
|
||||
patternBuilder.append('.');
|
||||
} else if ("**".equals(match)) {
|
||||
patternBuilder.append(".*");
|
||||
} else if ("*".equals(match)) {
|
||||
patternBuilder.append("[^/]*");
|
||||
}
|
||||
|
||||
end = m.end();
|
||||
}
|
||||
|
||||
patternBuilder.append(quote(path, end, path.length()));
|
||||
return patternBuilder.toString();
|
||||
}
|
||||
|
||||
private static String quote(String s, int start, int end) {
|
||||
if (start == end) {
|
||||
return "";
|
||||
}
|
||||
return Pattern.quote(s.substring(start, end));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.gridfs;
|
||||
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
|
||||
/**
|
||||
* GridFs-specific helper class to define {@link Criteria}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class GridFsCriteria extends Criteria {
|
||||
|
||||
/**
|
||||
* Creates a new {@link GridFsCriteria} for the given key.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public GridFsCriteria(String key) {
|
||||
super(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GridFsCriteria} for restrictions on the file's metadata.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static GridFsCriteria whereMetaData() {
|
||||
return new GridFsCriteria("metadata");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GridFsCriteria} for restrictions on a single file's metadata item.
|
||||
*
|
||||
* @param metadataKey
|
||||
* @return
|
||||
*/
|
||||
public static GridFsCriteria whereMetaData(String metadataKey) {
|
||||
String extension = metadataKey == null ? "" : "." + metadataKey;
|
||||
return new GridFsCriteria(String.format("metadata%s", extension));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GridFsCriteria} for restrictions on the file's name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static GridFsCriteria whereFilename() {
|
||||
return new GridFsCriteria("filename");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GridFsCriteria} for restrictions on the file's content type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static GridFsCriteria whereContentType() {
|
||||
return new GridFsCriteria("contentType");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.gridfs;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
import com.mongodb.gridfs.GridFSFile;
|
||||
|
||||
/**
|
||||
* Collection of operations to store and read files from MongoDB GridFS.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface GridFsOperations extends ResourcePatternResolver {
|
||||
|
||||
/**
|
||||
* Stores the given content into a file with the given name.
|
||||
*
|
||||
* @param content must not be {@literal null}.
|
||||
* @param filename must not be {@literal null} or empty.
|
||||
* @return the {@link GridFSFile} just created
|
||||
*/
|
||||
GridFSFile store(InputStream content, String filename);
|
||||
|
||||
/**
|
||||
* Stores the given content into a file with the given name using the given metadata. The metadata object will be
|
||||
* marshalled before writing.
|
||||
*
|
||||
* @param content must not be {@literal null}.
|
||||
* @param filename must not be {@literal null} or empty.
|
||||
* @param metadata
|
||||
* @return the {@link GridFSFile} just created
|
||||
*/
|
||||
GridFSFile store(InputStream content, String filename, Object metadata);
|
||||
|
||||
/**
|
||||
* Stores the given content into a file with the given name using the given metadata.
|
||||
*
|
||||
* @param content must not be {@literal null}.
|
||||
* @param filename must not be {@literal null} or empty.
|
||||
* @param metadata must not be {@literal null}.
|
||||
* @return the {@link GridFSFile} just created
|
||||
*/
|
||||
GridFSFile store(InputStream content, String filename, DBObject metadata);
|
||||
|
||||
/**
|
||||
* Returns all files matching the given query.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
List<GridFSDBFile> find(Query query);
|
||||
|
||||
/**
|
||||
* Returns a single file matching the given query or {@literal null} in case no file matches.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
GridFSDBFile findOne(Query query);
|
||||
|
||||
/**
|
||||
* Deletes all files matching the given {@link Query}.
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
void delete(Query query);
|
||||
|
||||
/**
|
||||
* Returns all {@link GridFsResource} with the given file name.
|
||||
*
|
||||
* @param filename
|
||||
* @return
|
||||
* @see ResourcePatternResolver#getResource(String)
|
||||
*/
|
||||
GridFsResource getResource(String filename);
|
||||
|
||||
/**
|
||||
* Returns all {@link GridFsResource}s matching the given file name pattern.
|
||||
*
|
||||
* @param filenamePattern
|
||||
* @return
|
||||
* @see ResourcePatternResolver#getResources(String)
|
||||
*/
|
||||
GridFsResource[] getResources(String filenamePattern);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.gridfs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
|
||||
/**
|
||||
* {@link GridFSDBFile} based {@link Resource} implementation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class GridFsResource extends InputStreamResource {
|
||||
|
||||
private final GridFSDBFile file;
|
||||
|
||||
/**
|
||||
* Creates a new {@link GridFsResource} from the given {@link GridFSDBFile}.
|
||||
*
|
||||
* @param file must not be {@literal null}.
|
||||
*/
|
||||
public GridFsResource(GridFSDBFile file) {
|
||||
super(file.getInputStream());
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.AbstractResource#contentLength()
|
||||
*/
|
||||
@Override
|
||||
public long contentLength() throws IOException {
|
||||
return file.getLength();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.AbstractResource#getFilename()
|
||||
*/
|
||||
@Override
|
||||
public String getFilename() throws IllegalStateException {
|
||||
return file.getFilename();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.AbstractResource#lastModified()
|
||||
*/
|
||||
@Override
|
||||
public long lastModified() throws IOException {
|
||||
return file.getUploadDate().getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Resource}'s id.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Object getId() {
|
||||
return file.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Resource}'s content type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getContentType() {
|
||||
return file.getContentType();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.gridfs;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.gridfs.GridFS;
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
import com.mongodb.gridfs.GridFSFile;
|
||||
import com.mongodb.gridfs.GridFSInputFile;
|
||||
|
||||
/**
|
||||
* {@link GridFsOperations} implementation to store content into MongoDB GridFS.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver {
|
||||
|
||||
private final MongoDbFactory dbFactory;
|
||||
private final String bucket;
|
||||
private final MongoConverter converter;
|
||||
private final QueryMapper queryMapper;
|
||||
|
||||
/**
|
||||
* Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}.
|
||||
*
|
||||
* @param dbFactory must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
*/
|
||||
public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter) {
|
||||
this(dbFactory, converter, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}.
|
||||
*
|
||||
* @param dbFactory must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
* @param bucket
|
||||
*/
|
||||
public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter, String bucket) {
|
||||
|
||||
Assert.notNull(dbFactory);
|
||||
Assert.notNull(converter);
|
||||
|
||||
this.dbFactory = dbFactory;
|
||||
this.converter = converter;
|
||||
this.bucket = bucket;
|
||||
|
||||
this.queryMapper = new QueryMapper(converter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String)
|
||||
*/
|
||||
public GridFSFile store(InputStream content, String filename) {
|
||||
return store(content, filename, (Object) null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public GridFSFile store(InputStream content, String filename, Object metadata) {
|
||||
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
converter.write(metadata, dbObject);
|
||||
return store(content, filename, dbObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.DBObject)
|
||||
*/
|
||||
public GridFSFile store(InputStream content, String filename, DBObject metadata) {
|
||||
|
||||
Assert.notNull(content);
|
||||
Assert.hasText(filename);
|
||||
Assert.notNull(metadata);
|
||||
|
||||
GridFSInputFile file = getGridFs().createFile(content);
|
||||
file.setFilename(filename);
|
||||
file.setMetaData(metadata);
|
||||
file.save();
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#find(com.mongodb.DBObject)
|
||||
*/
|
||||
public List<GridFSDBFile> find(Query query) {
|
||||
return getGridFs().find(getMappedQuery(query));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#findOne(com.mongodb.DBObject)
|
||||
*/
|
||||
public GridFSDBFile findOne(Query query) {
|
||||
return getGridFs().findOne(getMappedQuery(query));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#delete(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
public void delete(Query query) {
|
||||
getGridFs().remove(getMappedQuery(query));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.ResourceLoader#getClassLoader()
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
return dbFactory.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.ResourceLoader#getResource(java.lang.String)
|
||||
*/
|
||||
public GridFsResource getResource(String location) {
|
||||
return new GridFsResource(findOne(query(whereFilename().is(location))));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.io.support.ResourcePatternResolver#getResources(java.lang.String)
|
||||
*/
|
||||
public GridFsResource[] getResources(String locationPattern) {
|
||||
|
||||
if (!StringUtils.hasText(locationPattern)) {
|
||||
return new GridFsResource[0];
|
||||
}
|
||||
|
||||
AntPath path = new AntPath(locationPattern);
|
||||
|
||||
if (path.isPattern()) {
|
||||
|
||||
List<GridFSDBFile> files = find(query(whereFilename().regex(path.toRegex())));
|
||||
List<GridFsResource> resources = new ArrayList<GridFsResource>(files.size());
|
||||
|
||||
for (GridFSDBFile file : files) {
|
||||
resources.add(new GridFsResource(file));
|
||||
}
|
||||
|
||||
return resources.toArray(new GridFsResource[resources.size()]);
|
||||
}
|
||||
|
||||
return new GridFsResource[] { getResource(locationPattern) };
|
||||
}
|
||||
|
||||
private DBObject getMappedQuery(Query query) {
|
||||
return query == null ? null : queryMapper.getMappedObject(query.getQueryObject(), null);
|
||||
}
|
||||
|
||||
private GridFS getGridFs() {
|
||||
DB db = dbFactory.getDb();
|
||||
return bucket == null ? new GridFS(db) : new GridFS(db, bucket);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.monitor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.mongodb.core.MongoDbUtils;
|
||||
|
||||
import com.mongodb.CommandResult;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.mongodb.core.MongoDbUtils;
|
||||
|
||||
/**
|
||||
* Base class to encapsulate common configuration settings when connecting to a database
|
||||
@@ -30,7 +32,7 @@ import org.springframework.data.mongodb.core.MongoDbUtils;
|
||||
*/
|
||||
public abstract class AbstractMonitor {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected Mongo mongo;
|
||||
private String username;
|
||||
@@ -51,7 +53,6 @@ public abstract class AbstractMonitor {
|
||||
* @param password The password to use
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@@ -65,6 +66,6 @@ public abstract class AbstractMonitor {
|
||||
}
|
||||
|
||||
public DB getDb(String databaseName) {
|
||||
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
|
||||
return MongoDbUtils.getDB(mongo, databaseName, new UserCredentials(username, password));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,22 +32,19 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#save(java.lang.Iterable)
|
||||
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
|
||||
*/
|
||||
List<T> save(Iterable<? extends T> entites);
|
||||
<S extends T> List<S> save(Iterable<S> entites);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#findAll()
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.CrudRepository#findAll()
|
||||
*/
|
||||
List<T> findAll();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
|
||||
*/
|
||||
List<T> findAll(Sort sort);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.cdi;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link CdiRepositoryBean} to create Mongo repository instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
|
||||
private final Bean<MongoOperations> operations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoRepositoryBean}.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param qualifiers must not be {@literal null}.
|
||||
* @param repositoryType must not be {@literal null}.
|
||||
* @param beanManager must not be {@literal null}.
|
||||
*/
|
||||
public MongoRepositoryBean(Bean<MongoOperations> operations, Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager) {
|
||||
|
||||
super(qualifiers, repositoryType, beanManager);
|
||||
|
||||
Assert.notNull(operations);
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.enterprise.inject.spi.Bean#getScope()
|
||||
*/
|
||||
public Class<? extends Annotation> getScope() {
|
||||
return operations.getScope();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
|
||||
|
||||
MongoOperations mongoOperations = getDependencyInstance(operations, MongoOperations.class);
|
||||
MongoRepositoryFactory factory = new MongoRepositoryFactory(mongoOperations);
|
||||
|
||||
return factory.getRepository(repositoryType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.cdi;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.enterprise.inject.UnsatisfiedResolutionException;
|
||||
import javax.enterprise.inject.spi.AfterBeanDiscovery;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.ProcessBean;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
|
||||
/**
|
||||
* CDI extension to export Mongo repositories.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoRepositoryExtension extends CdiRepositoryExtensionSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MongoRepositoryExtension.class);
|
||||
|
||||
private final Map<Set<Annotation>, Bean<MongoOperations>> mongoOperations = new HashMap<Set<Annotation>, Bean<MongoOperations>>();
|
||||
|
||||
public MongoRepositoryExtension() {
|
||||
LOG.info("Activating CDI extension for Spring Data MongoDB repositories.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<X> void processBean(@Observes ProcessBean<X> processBean) {
|
||||
|
||||
Bean<X> bean = processBean.getBean();
|
||||
|
||||
for (Type type : bean.getTypes()) {
|
||||
if (type instanceof Class<?> && MongoOperations.class.isAssignableFrom((Class<?>) type)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format("Discovered %s with qualifiers %s.", MongoOperations.class.getName(),
|
||||
bean.getQualifiers()));
|
||||
}
|
||||
|
||||
// Store the EntityManager bean using its qualifiers.
|
||||
mongoOperations.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<MongoOperations>) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
|
||||
|
||||
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
|
||||
|
||||
Class<?> repositoryType = entry.getKey();
|
||||
Set<Annotation> qualifiers = entry.getValue();
|
||||
|
||||
// Create the bean representing the repository.
|
||||
Bean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
|
||||
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(), qualifiers));
|
||||
}
|
||||
|
||||
// Register the bean to the container.
|
||||
afterBeanDiscovery.addBean(repositoryBean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Bean}.
|
||||
*
|
||||
* @param <T> The type of the repository.
|
||||
* @param repositoryType The class representing the repository.
|
||||
* @param beanManager The BeanManager instance.
|
||||
* @return The bean.
|
||||
*/
|
||||
private <T> Bean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers, BeanManager beanManager) {
|
||||
|
||||
// Determine the MongoOperations bean which matches the qualifiers of the repository.
|
||||
Bean<MongoOperations> mongoOperations = this.mongoOperations.get(qualifiers);
|
||||
|
||||
if (mongoOperations == null) {
|
||||
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
|
||||
MongoOperations.class.getName(), qualifiers));
|
||||
}
|
||||
|
||||
// Construct and return the repository bean.
|
||||
return new MongoRepositoryBean<T>(mongoOperations, qualifiers, repositoryType, beanManager);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
|
||||
/**
|
||||
* Annotation to activate MongoDB repositories. If no base package is configured through either {@link #value()},
|
||||
* {@link #basePackages()} or {@link #basePackageClasses()} it will trigger scanning of the package of annotated class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(MongoRepositoriesRegistrar.class)
|
||||
public @interface EnableMongoRepositories {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
|
||||
* {@code @EnableJpaRepositories("org.my.pkg")} instead of {@code @EnableJpaRepositories(basePackages="org.my.pkg")}.
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
|
||||
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
|
||||
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
|
||||
* each package that serves no purpose other than being referenced by this attribute.
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
/**
|
||||
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
|
||||
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
|
||||
*/
|
||||
Filter[] includeFilters() default {};
|
||||
|
||||
/**
|
||||
* Specifies which types are not eligible for component scanning.
|
||||
*/
|
||||
Filter[] excludeFilters() default {};
|
||||
|
||||
/**
|
||||
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So
|
||||
* for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning
|
||||
* for {@code PersonRepositoryImpl}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String repositoryImplementationPostfix() default "";
|
||||
|
||||
/**
|
||||
* Configures the location of where to find the Spring Data named queries properties file. Will default to
|
||||
* {@code META-INFO/mongo-named-queries.properties}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
/**
|
||||
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
|
||||
* {@link Key#CREATE_IF_NOT_FOUND}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* Returns the {@link FactoryBean} class to be used for each repository instance. Defaults to
|
||||
* {@link MongoRepositoryFactoryBean}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> repositoryFactoryBeanClass() default MongoRepositoryFactoryBean.class;
|
||||
|
||||
/**
|
||||
* Configures the name of the {@link MongoTemplate} bean to be used with the repositories detected.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String mongoTemplateRef() default "mongoTemplate";
|
||||
|
||||
/**
|
||||
* Whether to automatically create indexes for query methods defined in the repository interface.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean createIndexesForQueryMethods() default false;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* Mongo-specific {@link ImportBeanDefinitionRegistrar}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MongoRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getAnnotation()
|
||||
*/
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableMongoRepositories.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getExtension()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new MongoRepositoryConfigurationExtension();
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.data.mongodb.repository.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration;
|
||||
import org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} to create Mongo DB repositories from classpath
|
||||
* scanning or manual definition.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoRepositoryConfigParser extends
|
||||
AbstractRepositoryConfigDefinitionParser<SimpleMongoRepositoryConfiguration, MongoRepositoryConfiguration> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#getGlobalRepositoryConfigInformation(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected SimpleMongoRepositoryConfiguration getGlobalRepositoryConfigInformation(Element element) {
|
||||
|
||||
return new SimpleMongoRepositoryConfiguration(element);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#postProcessBeanDefinition(org.springframework.data.repository.config.SingleRepositoryConfigInformation, org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeanDefinition(MongoRepositoryConfiguration context, BeanDefinitionBuilder builder,
|
||||
BeanDefinitionRegistry registry, Object beanSource) {
|
||||
|
||||
builder.addPropertyReference("template", context.getMongoTemplateRef());
|
||||
builder.addPropertyValue("createIndexesForQueryMethods", context.getCreateQueryIndexes());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.XmlRepositoryConfigurationSource;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link RepositoryConfigurationExtension} for MongoDB.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
|
||||
private static final String CREATE_QUERY_INDEXES = "create-query-indexes";
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix()
|
||||
*/
|
||||
@Override
|
||||
protected String getModulePrefix() {
|
||||
return "mongo";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryClassName()
|
||||
*/
|
||||
public String getRepositoryFactoryClassName() {
|
||||
return MongoRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.XmlRepositoryConfigurationSource)
|
||||
*/
|
||||
@Override
|
||||
public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) {
|
||||
|
||||
Element element = config.getElement();
|
||||
|
||||
ParsingUtils.setPropertyReference(builder, element, MONGO_TEMPLATE_REF, "mongoOperations");
|
||||
ParsingUtils.setPropertyValue(builder, element, CREATE_QUERY_INDEXES, "createIndexesForQueryMethods");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource)
|
||||
*/
|
||||
@Override
|
||||
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) {
|
||||
|
||||
AnnotationAttributes attributes = config.getAttributes();
|
||||
|
||||
builder.addPropertyReference("mongoOperations", attributes.getString("mongoTemplateRef"));
|
||||
builder.addPropertyValue("createIndexesForQueryMethods", attributes.getBoolean("createIndexesForQueryMethods"));
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.config.AutomaticRepositoryConfigInformation;
|
||||
import org.springframework.data.repository.config.ManualRepositoryConfigInformation;
|
||||
import org.springframework.data.repository.config.RepositoryConfig;
|
||||
import org.springframework.data.repository.config.SingleRepositoryConfigInformation;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link RepositoryConfig} implementation to create {@link MongoRepositoryConfiguration} instances for both automatic
|
||||
* and manual configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SimpleMongoRepositoryConfiguration
|
||||
extends
|
||||
RepositoryConfig<SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration, SimpleMongoRepositoryConfiguration> {
|
||||
|
||||
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
|
||||
private static final String CREATE_QUERY_INDEXES = "create-query-indexes";
|
||||
private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate";
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleMongoRepositoryConfiguration} for the given {@link Element}.
|
||||
*
|
||||
* @param repositoriesElement
|
||||
*/
|
||||
protected SimpleMongoRepositoryConfiguration(Element repositoriesElement) {
|
||||
|
||||
super(repositoriesElement, MongoRepositoryFactoryBean.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bean name of the {@link org.springframework.data.mongodb.core.core.MongoTemplate} to be referenced.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getMongoTemplateRef() {
|
||||
|
||||
String templateRef = getSource().getAttribute(MONGO_TEMPLATE_REF);
|
||||
return StringUtils.hasText(templateRef) ? templateRef : DEFAULT_MONGO_TEMPLATE_REF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to create indexes for query methods.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean getCreateQueryIndexes() {
|
||||
|
||||
String createQueryIndexes = getSource().getAttribute(CREATE_QUERY_INDEXES);
|
||||
return StringUtils.hasText(createQueryIndexes) ? Boolean.parseBoolean(createQueryIndexes) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
||||
* #getAutoconfigRepositoryInformation(java.lang.String)
|
||||
*/
|
||||
public MongoRepositoryConfiguration getAutoconfigRepositoryInformation(String interfaceName) {
|
||||
|
||||
return new AutomaticMongoRepositoryConfiguration(interfaceName, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfig#getNamedQueriesLocation()
|
||||
*/
|
||||
public String getNamedQueriesLocation() {
|
||||
return "classpath*:META-INF/mongo-named-queries.properties";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.config.RepositoryConfig#
|
||||
* createSingleRepositoryConfigInformationFor(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected MongoRepositoryConfiguration createSingleRepositoryConfigInformationFor(Element element) {
|
||||
|
||||
return new ManualMongoRepositoryConfiguration(element, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface for configuration values specific to Mongo repositories.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoRepositoryConfiguration extends
|
||||
SingleRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> {
|
||||
|
||||
String getMongoTemplateRef();
|
||||
|
||||
boolean getCreateQueryIndexes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements manual lookup of the additional attributes.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ManualMongoRepositoryConfiguration extends
|
||||
ManualRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> implements MongoRepositoryConfiguration {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ManualMongoRepositoryConfiguration} for the given {@link Element} and parent.
|
||||
*
|
||||
* @param element
|
||||
* @param parent
|
||||
*/
|
||||
public ManualMongoRepositoryConfiguration(Element element, SimpleMongoRepositoryConfiguration parent) {
|
||||
|
||||
super(element, parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.mongodb.repository.config.
|
||||
* SimpleMongoRepositoryConfiguration
|
||||
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
||||
*/
|
||||
public String getMongoTemplateRef() {
|
||||
|
||||
return getAttribute(MONGO_TEMPLATE_REF);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getCreateQueryIndexes()
|
||||
*/
|
||||
public boolean getCreateQueryIndexes() {
|
||||
|
||||
String attribute = getAttribute(CREATE_QUERY_INDEXES);
|
||||
return attribute == null ? false : Boolean.parseBoolean(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the lookup of the additional attributes during automatic configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class AutomaticMongoRepositoryConfiguration extends
|
||||
AutomaticRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> implements MongoRepositoryConfiguration {
|
||||
|
||||
/**
|
||||
* Creates a new {@link AutomaticMongoRepositoryConfiguration} for the given interface and parent.
|
||||
*
|
||||
* @param interfaceName
|
||||
* @param parent
|
||||
*/
|
||||
public AutomaticMongoRepositoryConfiguration(String interfaceName, SimpleMongoRepositoryConfiguration parent) {
|
||||
|
||||
super(interfaceName, parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.mongodb.repository.config.
|
||||
* SimpleMongoRepositoryConfiguration
|
||||
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
||||
*/
|
||||
public String getMongoTemplateRef() {
|
||||
|
||||
return getParent().getMongoTemplateRef();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getCreateQueryIndexes()
|
||||
*/
|
||||
public boolean getCreateQueryIndexes() {
|
||||
return getParent().getCreateQueryIndexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,9 +21,9 @@ import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.GeoPage;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
@@ -34,10 +34,6 @@ import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base class for {@link RepositoryQuery} implementations for Mongo.
|
||||
*
|
||||
@@ -46,45 +42,50 @@ import com.mongodb.DBObject;
|
||||
public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
private final MongoQueryMethod method;
|
||||
private final MongoTemplate template;
|
||||
private final MongoOperations operations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoTemplate}.
|
||||
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
|
||||
*
|
||||
* @param method
|
||||
* @param template
|
||||
* @param method must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
*/
|
||||
public AbstractMongoQuery(MongoQueryMethod method, MongoTemplate template) {
|
||||
public AbstractMongoQuery(MongoQueryMethod method, MongoOperations operations) {
|
||||
|
||||
Assert.notNull(template);
|
||||
Assert.notNull(operations);
|
||||
Assert.notNull(method);
|
||||
|
||||
this.method = method;
|
||||
this.template = template;
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
|
||||
*/
|
||||
public MongoQueryMethod getQueryMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java .lang.Object[])
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method, parameters);
|
||||
Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
|
||||
Query query = createQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));
|
||||
|
||||
if (method.isGeoNearQuery()) {
|
||||
if (method.isGeoNearQuery() && method.isPageQuery()) {
|
||||
|
||||
MongoParameterAccessor countAccessor = new MongoParametersParameterAccessor(method, parameters);
|
||||
Query countQuery = createCountQuery(new ConvertingParameterAccessor(operations.getConverter(), countAccessor));
|
||||
|
||||
return new GeoNearExecution(accessor).execute(query, countQuery);
|
||||
} else if (method.isGeoNearQuery()) {
|
||||
return new GeoNearExecution(accessor).execute(query);
|
||||
} else if (method.isCollectionQuery()) {
|
||||
return new CollectionExecution().execute(query);
|
||||
return new CollectionExecution(accessor.getPageable()).execute(query);
|
||||
} else if (method.isPageQuery()) {
|
||||
return new PagedExecution(accessor.getPageable()).execute(query);
|
||||
} else {
|
||||
@@ -93,14 +94,25 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Query} instance using the given {@link ParameterAccessor}
|
||||
* Creates a {@link Query} instance using the given {@link ParameterAccessor}
|
||||
*
|
||||
* @param accessor
|
||||
* @param converter
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected abstract Query createQuery(ConvertingParameterAccessor accessor);
|
||||
|
||||
/**
|
||||
* Creates a {@link Query} instance using the given {@link ConvertingParameterAccessor}. Will delegate to
|
||||
* {@link #createQuery(ConvertingParameterAccessor)} by default but allows customization of the count query to be
|
||||
* triggered.
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
|
||||
return createQuery(accessor);
|
||||
}
|
||||
|
||||
private abstract class Execution {
|
||||
|
||||
abstract Object execute(Query query);
|
||||
@@ -110,7 +122,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
|
||||
String collectionName = metadata.getCollectionName();
|
||||
return template.find(query, metadata.getJavaType(), collectionName);
|
||||
return operations.find(query, metadata.getJavaType(), collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,14 +133,23 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
class CollectionExecution extends Execution {
|
||||
|
||||
private final Pageable pageable;
|
||||
|
||||
CollectionExecution(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query) {
|
||||
|
||||
if (pageable != null) {
|
||||
query = applyPagination(query, pageable);
|
||||
}
|
||||
|
||||
return readCollection(query);
|
||||
}
|
||||
}
|
||||
@@ -162,24 +183,13 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
int count = getCollectionCursor(metadata.getCollectionName(), query.getQueryObject()).count();
|
||||
long count = operations.count(query, metadata.getCollectionName());
|
||||
|
||||
List<?> result = template.find(applyPagination(query, pageable), metadata.getJavaType(),
|
||||
List<?> result = operations.find(applyPagination(query, pageable), metadata.getJavaType(),
|
||||
metadata.getCollectionName());
|
||||
|
||||
return new PageImpl(result, pageable, count);
|
||||
}
|
||||
|
||||
private DBCursor getCollectionCursor(String collectionName, final DBObject query) {
|
||||
|
||||
return template.execute(collectionName, new CollectionCallback<DBCursor>() {
|
||||
|
||||
public DBCursor doInCollection(DBCollection collection) {
|
||||
|
||||
return collection.find(query);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,19 +207,19 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return template.findOne(query, entityInformation.getJavaType());
|
||||
return operations.findOne(query, entityInformation.getJavaType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} to execute geo-near queries.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class GeoNearExecution extends Execution {
|
||||
|
||||
|
||||
private final MongoParameterAccessor accessor;
|
||||
|
||||
|
||||
public GeoNearExecution(MongoParameterAccessor accessor) {
|
||||
this.accessor = accessor;
|
||||
}
|
||||
@@ -220,27 +230,48 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
|
||||
GeoResults<?> results = doExecuteQuery(query);
|
||||
return isListOfGeoResult() ? results.getContent() : results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Query} to return a page.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param countQuery must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object execute(Query query, Query countQuery) {
|
||||
|
||||
MongoEntityInformation<?, ?> information = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, information.getCollectionName());
|
||||
|
||||
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private GeoResults<Object> doExecuteQuery(Query query) {
|
||||
|
||||
Point nearLocation = accessor.getGeoNearLocation();
|
||||
NearQuery nearQuery = NearQuery.near(nearLocation);
|
||||
|
||||
|
||||
if (query != null) {
|
||||
nearQuery.query(query);
|
||||
}
|
||||
|
||||
|
||||
Distance maxDistance = accessor.getMaxDistance();
|
||||
if (maxDistance != null) {
|
||||
nearQuery.maxDistance(maxDistance);
|
||||
}
|
||||
|
||||
MongoEntityInformation<?,?> entityInformation = method.getEntityInformation();
|
||||
GeoResults<?> results = template.geoNear(nearQuery, entityInformation.getJavaType(), entityInformation.getCollectionName());
|
||||
|
||||
return isListOfGeoResult() ? results.getContent() : results;
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
|
||||
private boolean isListOfGeoResult() {
|
||||
|
||||
|
||||
TypeInformation<?> returnType = method.getReturnType();
|
||||
return returnType.getType().equals(List.class) && GeoResult.class.equals(returnType.getComponentType());
|
||||
}
|
||||
|
||||
@@ -20,13 +20,11 @@ import java.util.Iterator;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.convert.MongoWriter;
|
||||
import org.springframework.data.mongodb.core.convert.TypeKeyAware;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Custom {@link ParameterAccessor} that uses a {@link MongoWriter} to serialize parameters into Mongo format.
|
||||
@@ -41,9 +39,14 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
/**
|
||||
* Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
|
||||
*
|
||||
* @param writer
|
||||
* @param writer must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public ConvertingParameterAccessor(MongoWriter<?> writer, MongoParameterAccessor delegate) {
|
||||
|
||||
Assert.notNull(writer);
|
||||
Assert.notNull(delegate);
|
||||
|
||||
this.writer = writer;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
@@ -90,7 +93,7 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
public Distance getMaxDistance() {
|
||||
return delegate.getMaxDistance();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
|
||||
*/
|
||||
@@ -105,49 +108,15 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
* @return
|
||||
*/
|
||||
private Object getConvertedValue(Object value) {
|
||||
|
||||
if (!(writer instanceof TypeKeyAware)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return removeTypeInfoRecursively(writer.convertToMongoType(value), ((TypeKeyAware) writer));
|
||||
return writer.convertToMongoType(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the type information from the conversion result.
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#hasBindableNullValue()
|
||||
*/
|
||||
private Object removeTypeInfoRecursively(Object object, TypeKeyAware typeKeyAware) {
|
||||
|
||||
if (!(object instanceof DBObject) || typeKeyAware == null) {
|
||||
return object;
|
||||
}
|
||||
|
||||
DBObject dbObject = (DBObject) object;
|
||||
String keyToRemove = null;
|
||||
for (String key : dbObject.keySet()) {
|
||||
|
||||
if (typeKeyAware.isTypeKey(key)) {
|
||||
keyToRemove = key;
|
||||
}
|
||||
|
||||
Object value = dbObject.get(key);
|
||||
if (value instanceof BasicDBList) {
|
||||
for (Object element : (BasicDBList) value) {
|
||||
removeTypeInfoRecursively(element, typeKeyAware);
|
||||
}
|
||||
} else {
|
||||
removeTypeInfoRecursively(value, typeKeyAware);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyToRemove != null) {
|
||||
dbObject.removeField(keyToRemove);
|
||||
}
|
||||
|
||||
return dbObject;
|
||||
public boolean hasBindableNullValue() {
|
||||
return delegate.hasBindableNullValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,37 +138,33 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return delegate.hasNext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
public Object next() {
|
||||
|
||||
return delegate.next();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.ConvertingParameterAccessor.PotentiallConvertingIterator#nextConverted()
|
||||
*/
|
||||
public Object nextConverted() {
|
||||
|
||||
return getConvertedValue(next());
|
||||
public Object nextConverted(MongoPersistentProperty property) {
|
||||
return property.isAssociation() ? writer.toDBRef(next(), property) : getConvertedValue(next());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
public void remove() {
|
||||
delegate.remove();
|
||||
}
|
||||
@@ -217,6 +182,6 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Object nextConverted();
|
||||
Object nextConverted(MongoPersistentProperty property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,9 @@ package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for components being able to provide {@link EntityInformationCreator} for a given {@link Class}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface EntityInformationCreator {
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface MongoParameterAccessor extends ParameterAccessor {
|
||||
* at all or the given value for it was {@literal null}.
|
||||
*/
|
||||
Distance getMaxDistance();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link Point} to use for a geo-near query.
|
||||
*
|
||||
|
||||
@@ -35,7 +35,7 @@ public class MongoParameters extends Parameters {
|
||||
|
||||
private final Integer distanceIndex;
|
||||
private Integer nearIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParameters} instance from the given {@link Method} and {@link MongoQueryMethod}.
|
||||
*
|
||||
@@ -43,55 +43,56 @@ public class MongoParameters extends Parameters {
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
*/
|
||||
public MongoParameters(Method method, boolean isGeoNearMethod) {
|
||||
|
||||
|
||||
super(method);
|
||||
List<Class<?>> parameterTypes = Arrays.asList(method.getParameterTypes());
|
||||
this.distanceIndex = parameterTypes.indexOf(Distance.class);
|
||||
|
||||
|
||||
if (this.nearIndex == null && isGeoNearMethod) {
|
||||
this.nearIndex = getNearIndex(parameterTypes);
|
||||
} else if (this.nearIndex == null) {
|
||||
this.nearIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final int getNearIndex(List<Class<?>> parameterTypes) {
|
||||
|
||||
|
||||
for (Class<?> reference : Arrays.asList(Point.class, double[].class)) {
|
||||
|
||||
|
||||
int nearIndex = parameterTypes.indexOf(reference);
|
||||
|
||||
|
||||
if (nearIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (nearIndex == parameterTypes.lastIndexOf(reference)) {
|
||||
return nearIndex;
|
||||
} else {
|
||||
throw new IllegalStateException("Multiple Point parameters found but none annotated with @Near!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.Parameters#createParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
protected Parameter createParameter(MethodParameter parameter) {
|
||||
|
||||
|
||||
MongoParameter mongoParameter = new MongoParameter(parameter);
|
||||
|
||||
|
||||
// Detect manually annotated @Near Point and reject multiple annotated ones
|
||||
if (this.nearIndex == null && mongoParameter.isManuallyAnnotatedNearParameter()) {
|
||||
this.nearIndex = mongoParameter.getIndex();
|
||||
} else if (mongoParameter.isManuallyAnnotatedNearParameter()) {
|
||||
throw new IllegalStateException(String.format("Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
|
||||
throw new IllegalStateException(String.format(
|
||||
"Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
|
||||
}
|
||||
|
||||
|
||||
return mongoParameter;
|
||||
}
|
||||
|
||||
@@ -103,7 +104,7 @@ public class MongoParameters extends Parameters {
|
||||
public int getDistanceIndex() {
|
||||
return distanceIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the parameter to be used to start a geo-near query from.
|
||||
*
|
||||
@@ -112,16 +113,16 @@ public class MongoParameters extends Parameters {
|
||||
public int getNearIndex() {
|
||||
return nearIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MongoParameter extends Parameter {
|
||||
|
||||
|
||||
private final MethodParameter parameter;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParameter}.
|
||||
*
|
||||
@@ -130,7 +131,7 @@ public class MongoParameters extends Parameters {
|
||||
MongoParameter(MethodParameter parameter) {
|
||||
super(parameter);
|
||||
this.parameter = parameter;
|
||||
|
||||
|
||||
if (!isPoint() && hasNearAnnotation()) {
|
||||
throw new IllegalArgumentException("Near annotation is only allowed at Point parameter!");
|
||||
}
|
||||
@@ -142,23 +143,22 @@ public class MongoParameters extends Parameters {
|
||||
*/
|
||||
@Override
|
||||
public boolean isSpecialParameter() {
|
||||
return super.isSpecialParameter() || getType().equals(Distance.class)
|
||||
|| isNearParameter();
|
||||
return super.isSpecialParameter() || getType().equals(Distance.class) || isNearParameter();
|
||||
}
|
||||
|
||||
|
||||
private boolean isNearParameter() {
|
||||
Integer nearIndex = MongoParameters.this.nearIndex;
|
||||
return nearIndex != null && nearIndex.equals(getIndex());
|
||||
}
|
||||
|
||||
|
||||
private boolean isManuallyAnnotatedNearParameter() {
|
||||
return isPoint() && hasNearAnnotation();
|
||||
}
|
||||
|
||||
|
||||
private boolean isPoint() {
|
||||
return getType().equals(Point.class) || getType().equals(double[].class);
|
||||
}
|
||||
|
||||
|
||||
private boolean hasNearAnnotation() {
|
||||
return parameter.getParameterAnnotation(Near.class) != null;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
|
||||
/**
|
||||
* Mongo-specific {@link ParametersParameterAccessor} to allow access to the {@link Distance} parameter.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParametersParameterAccessor extends ParametersParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final MongoQueryMethod method;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParametersParameterAccessor}.
|
||||
*
|
||||
@@ -47,25 +47,25 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
int index = method.getParameters().getDistanceIndex();
|
||||
return index == -1 ? null : (Distance) getValue(index);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
|
||||
*/
|
||||
public Point getGeoNearLocation() {
|
||||
|
||||
|
||||
int nearIndex = method.getParameters().getNearIndex();
|
||||
|
||||
|
||||
if (nearIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Object value = getValue(nearIndex);
|
||||
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (value instanceof double[]) {
|
||||
double[] typedValue = (double[]) value;
|
||||
if (typedValue.length != 2) {
|
||||
@@ -74,7 +74,7 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
return new Point(typedValue[0], typedValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (Point) value;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user