diff --git a/hapi-fhir-base/examples/.classpath b/hapi-fhir-base/examples/.classpath
new file mode 100644
index 00000000000..ce99802b301
--- /dev/null
+++ b/hapi-fhir-base/examples/.classpath
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-base/examples/.gitignore b/hapi-fhir-base/examples/.gitignore
new file mode 100644
index 00000000000..b83d22266ac
--- /dev/null
+++ b/hapi-fhir-base/examples/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/hapi-fhir-base/examples/.project b/hapi-fhir-base/examples/.project
new file mode 100644
index 00000000000..a0b8364c52b
--- /dev/null
+++ b/hapi-fhir-base/examples/.project
@@ -0,0 +1,23 @@
+
+
+ hapi-fhir-base-examples
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/hapi-fhir-base/examples/.settings/org.eclipse.core.resources.prefs b/hapi-fhir-base/examples/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 00000000000..e9441bb123e
--- /dev/null
+++ b/hapi-fhir-base/examples/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/=UTF-8
diff --git a/hapi-fhir-base/examples/.settings/org.eclipse.jdt.core.prefs b/hapi-fhir-base/examples/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..96bb6730c79
--- /dev/null
+++ b/hapi-fhir-base/examples/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,289 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=3
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=160
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=3
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/hapi-fhir-base/examples/.settings/org.eclipse.jdt.ui.prefs b/hapi-fhir-base/examples/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 00000000000..fb44b15814d
--- /dev/null
+++ b/hapi-fhir-base/examples/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+formatter_profile=_examples-format
+formatter_settings_version=12
diff --git a/hapi-fhir-base/examples/.settings/org.eclipse.m2e.core.prefs b/hapi-fhir-base/examples/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 00000000000..f897a7f1cb2
--- /dev/null
+++ b/hapi-fhir-base/examples/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/hapi-fhir-base/examples/pom.xml b/hapi-fhir-base/examples/pom.xml
new file mode 100644
index 00000000000..1a2e015b06d
--- /dev/null
+++ b/hapi-fhir-base/examples/pom.xml
@@ -0,0 +1,47 @@
+
+ 4.0.0
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir
+ 0.6-SNAPSHOT
+ ../../pom.xml
+
+
+ hapi-fhir-base-examples
+ jar
+
+ HAPI FHIR - Examples (for site)
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-base
+ 0.6-SNAPSHOT
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+ junit
+ junit
+ ${junit_version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
diff --git a/hapi-fhir-base/examples/src/main/java/example/ClientExamples.java b/hapi-fhir-base/examples/src/main/java/example/ClientExamples.java
new file mode 100644
index 00000000000..564feef7ee5
--- /dev/null
+++ b/hapi-fhir-base/examples/src/main/java/example/ClientExamples.java
@@ -0,0 +1,89 @@
+package example;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.client.IGenericClient;
+import ca.uhn.fhir.rest.client.IRestfulClientFactory;
+import ca.uhn.fhir.rest.client.api.IBasicClient;
+import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
+import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+
+public class ClientExamples {
+
+ public interface IPatientClient extends IBasicClient {
+ // nothing yet
+ }
+
+ @SuppressWarnings("unused")
+ public void createProxy() {
+ // START SNIPPET: proxy
+ FhirContext ctx = new FhirContext();
+ ctx.getRestfulClientFactory().setProxy("example.com", 8888);
+
+ IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
+ // END SNIPPET: proxy
+ }
+
+ @SuppressWarnings("unused")
+ public void createSecurity() {
+ // START SNIPPET: security
+ // Create a context and get the client factory so it can be configured
+ FhirContext ctx = new FhirContext();
+ IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
+
+ // Create an HTTP basic auth interceptor
+ String username = "foobar";
+ String password = "boobear";
+ BasicAuthInterceptor authInterceptor = new BasicAuthInterceptor(username, password);
+
+ // Register the interceptor with your client (either style)
+ IPatientClient annotationClient = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/fhir");
+ annotationClient.registerInterceptor(authInterceptor);
+
+ IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
+ annotationClient.registerInterceptor(authInterceptor);
+ // END SNIPPET: security
+ }
+
+ @SuppressWarnings("unused")
+ public void createLogging() {
+ {
+ // START SNIPPET: logging
+ // Create a context and get the client factory so it can be configured
+ FhirContext ctx = new FhirContext();
+ IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
+
+ // Create a logging interceptor
+ LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
+
+ // Optionally you may configure the interceptor (by default only
+ // summary info is logged)
+ loggingInterceptor.setLogRequestSummary(true);
+ loggingInterceptor.setLogRequestBody(true);
+
+ // Register the interceptor with your client (either style)
+ IPatientClient annotationClient = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/fhir");
+ annotationClient.registerInterceptor(loggingInterceptor);
+
+ IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
+ genericClient.registerInterceptor(loggingInterceptor);
+ // END SNIPPET: logging
+ }
+
+ /******************************/
+ {
+ // START SNIPPET: clientConfig
+ // Create a client
+ FhirContext ctx = new FhirContext();
+ IPatientClient client = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/");
+
+ // Request JSON encoding from the server (_format=json)
+ client.setEncoding(EncodingEnum.JSON);
+
+ // Request pretty printing from the server (_pretty=true)
+ client.setPrettyPrint(true);
+ // END SNIPPET: clientConfig
+ }
+ }
+
+}
diff --git a/hapi-fhir-base/examples/src/main/java/example/CompleteExampleClient.java b/hapi-fhir-base/examples/src/main/java/example/CompleteExampleClient.java
new file mode 100644
index 00000000000..50f6a4263a1
--- /dev/null
+++ b/hapi-fhir-base/examples/src/main/java/example/CompleteExampleClient.java
@@ -0,0 +1,66 @@
+package example;
+
+//START SNIPPET: client
+import java.io.IOException;
+import java.util.List;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
+import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
+import ca.uhn.fhir.model.dstu.resource.Organization;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.rest.annotation.RequiredParam;
+import ca.uhn.fhir.rest.annotation.Search;
+import ca.uhn.fhir.rest.client.api.IRestfulClient;
+
+public class CompleteExampleClient {
+
+ /**
+ * This is a simple client interface. It can have many methods for various
+ * searches but in this case it has only 1.
+ */
+ public static interface ClientInterface extends IRestfulClient {
+
+ /**
+ * This is translated into a URL similar to the following:
+ * http://fhir.healthintersections.com.au/open/Patient?identifier=urn:oid:1.2.36.146.595.217.0.1%7C12345
+ */
+ @Search
+ List findPatientsForMrn(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier);
+
+ }
+
+ /**
+ * The main method here will directly call an open FHIR server and retrieve a
+ * list of resources matching a given criteria, then load a linked resource.
+ */
+ public static void main(String[] args) throws IOException {
+
+ // Create a client factory
+ FhirContext ctx = new FhirContext();
+
+ // Create the client
+ String serverBase = "http://fhir.healthintersections.com.au/open";
+ ClientInterface client = ctx.newRestfulClient(ClientInterface.class, serverBase);
+
+ // Invoke the client to search for patient
+ List patients = client.findPatientsForMrn(new IdentifierDt("urn:oid:1.2.36.146.595.217.0.1", "12345"));
+
+ System.out.println("Found " + patients.size() + " patients");
+
+ // Print a value from the loaded resource
+ Patient patient = patients.get(0);
+ System.out.println("Patient Last Name: " + patient.getName().get(0).getFamily().get(0).getValue());
+
+ // Load a referenced resource
+ ResourceReferenceDt managingRef = patient.getManagingOrganization();
+ Organization org = (Organization) managingRef.loadResource(client);
+
+ // Print organization name
+ System.out.println(org.getName().getValue());
+
+ }
+
+}
+// END SNIPPET: client
+
diff --git a/hapi-fhir-base/src/site/example/java/example/ExampleProviders.java b/hapi-fhir-base/examples/src/main/java/example/ExampleProviders.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/ExampleProviders.java
rename to hapi-fhir-base/examples/src/main/java/example/ExampleProviders.java
diff --git a/hapi-fhir-base/src/site/example/java/example/ExampleRestfulClient.java b/hapi-fhir-base/examples/src/main/java/example/ExampleRestfulClient.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/ExampleRestfulClient.java
rename to hapi-fhir-base/examples/src/main/java/example/ExampleRestfulClient.java
diff --git a/hapi-fhir-base/src/site/example/java/example/ExampleRestfulServlet.java b/hapi-fhir-base/examples/src/main/java/example/ExampleRestfulServlet.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/ExampleRestfulServlet.java
rename to hapi-fhir-base/examples/src/main/java/example/ExampleRestfulServlet.java
diff --git a/hapi-fhir-base/src/site/example/java/example/Extensions.java b/hapi-fhir-base/examples/src/main/java/example/Extensions.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/Extensions.java
rename to hapi-fhir-base/examples/src/main/java/example/Extensions.java
diff --git a/hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java b/hapi-fhir-base/examples/src/main/java/example/FhirContextIntro.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/FhirContextIntro.java
rename to hapi-fhir-base/examples/src/main/java/example/FhirContextIntro.java
diff --git a/hapi-fhir-base/src/site/example/java/example/FhirDataModel.java b/hapi-fhir-base/examples/src/main/java/example/FhirDataModel.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/FhirDataModel.java
rename to hapi-fhir-base/examples/src/main/java/example/FhirDataModel.java
diff --git a/hapi-fhir-base/src/site/example/java/example/GenericClientExample.java b/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java
similarity index 91%
rename from hapi-fhir-base/src/site/example/java/example/GenericClientExample.java
rename to hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java
index 97920283720..4805c3f3411 100644
--- a/hapi-fhir-base/src/site/example/java/example/GenericClientExample.java
+++ b/hapi-fhir-base/examples/src/main/java/example/GenericClientExample.java
@@ -17,22 +17,19 @@ import ca.uhn.fhir.rest.method.SearchStyleEnum;
public class GenericClientExample {
-@SuppressWarnings("unused")
public static void simpleExample() {
// START SNIPPET: simple
FhirContext ctx = new FhirContext();
-String serverBase = "http://fhir.healthintersections.com.au/open";
+String serverBase = "http://fhirtest.uhn.ca/base";
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
-// Read a patient
-Patient patient = client.read(Patient.class, "1");
+// Perform a search
+Bundle results = client.search()
+ .forResource(Patient.class)
+ .where(Patient.FAMILY.matches().value("duck"))
+ .execute();
-// Change the patient and update it to the server
-patient.getNameFirstRep().getFamilyFirstRep().setValue("Jones");
-client.update("1", patient);
-
-// Return the version history for that patient
-Bundle versions = client.history(Patient.class, "1",null,null);
+System.out.println("Found " + results.size() + " patients named 'duck'");
// END SNIPPET: simple
}
@@ -177,7 +174,7 @@ List response = client.transaction()
}
public static void main(String[] args) {
- // nothing
+ simpleExample();
}
}
diff --git a/hapi-fhir-base/src/site/example/java/example/IRestfulClient.java b/hapi-fhir-base/examples/src/main/java/example/IRestfulClient.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/IRestfulClient.java
rename to hapi-fhir-base/examples/src/main/java/example/IRestfulClient.java
diff --git a/hapi-fhir-base/src/site/example/java/example/MyPatient.java b/hapi-fhir-base/examples/src/main/java/example/MyPatient.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/MyPatient.java
rename to hapi-fhir-base/examples/src/main/java/example/MyPatient.java
diff --git a/hapi-fhir-base/examples/src/main/java/example/MyPatientUse.java b/hapi-fhir-base/examples/src/main/java/example/MyPatientUse.java
new file mode 100644
index 00000000000..1604fb237c4
--- /dev/null
+++ b/hapi-fhir-base/examples/src/main/java/example/MyPatientUse.java
@@ -0,0 +1,86 @@
+package example;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.Description;
+import ca.uhn.fhir.model.api.annotation.Extension;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.model.primitive.DateTimeDt;
+import ca.uhn.fhir.model.primitive.StringDt;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+
+public class MyPatientUse {
+
+ @ResourceDef
+ public static class MyPatient extends Patient {
+
+ @Child(name="petName")
+ @Extension(url="http://example.com/dontuse#petname", definedLocally=false, isModifier=false)
+ @Description(shortDefinition="The name of the patient's favourite pet")
+ private StringDt myPetName;
+
+ public StringDt getPetName() {
+ if(myPetName==null) {
+ myPetName = new StringDt();
+ }
+ return myPetName;
+ }
+
+ public void setPetName(StringDt thePetName) {
+ myPetName = thePetName;
+ }
+
+ public List getImportantDates() {
+ if (myImportantDates==null) {
+ myImportantDates=new ArrayList();
+ }
+ return myImportantDates;
+ }
+
+ public void setImportantDates(List theImportantDates) {
+ myImportantDates = theImportantDates;
+ }
+
+ @Child(name="importantDates", max=Child.MAX_UNLIMITED)
+ @Extension(url="http://example.com/dontuse#importantDates", definedLocally=false, isModifier=true)
+ @Description(shortDefinition="Some dates of note for the patient")
+ private List myImportantDates;
+
+ }
+
+@SuppressWarnings("unused")
+public static void main(String[] args) throws DataFormatException, IOException {
+//START SNIPPET: patientUse
+MyPatient patient = new MyPatient();
+patient.setPetName(new StringDt("Fido"));
+patient.getImportantDates().add(new DateTimeDt("2010-01-02"));
+patient.getImportantDates().add(new DateTimeDt("2014-01-26T11:11:11"));
+
+patient.addName().addFamily("Smith").addGiven("John").addGiven("Quincy").addSuffix("Jr");
+
+IParser p = new FhirContext().newXmlParser().setPrettyPrint(true);
+String messageString = p.encodeResourceToString(patient);
+
+System.out.println(messageString);
+//END SNIPPET: patientUse
+
+//START SNIPPET: patientParse
+IParser parser = new FhirContext().newXmlParser();
+MyPatient newPatient = parser.parseResource(MyPatient.class, messageString);
+//END SNIPPET: patientParse
+
+{
+ FhirContext ctx2 = new FhirContext();
+ RuntimeResourceDefinition def = ctx2.getResourceDefinition(patient);
+ System.out.println(ctx2.newXmlParser().setPrettyPrint(true).encodeResourceToString(def.toProfile()));
+}
+}
+
+}
diff --git a/hapi-fhir-base/src/site/example/java/example/Narrative.java b/hapi-fhir-base/examples/src/main/java/example/Narrative.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/Narrative.java
rename to hapi-fhir-base/examples/src/main/java/example/Narrative.java
diff --git a/hapi-fhir-base/src/site/example/java/example/NarrativeGenerator.java b/hapi-fhir-base/examples/src/main/java/example/NarrativeGenerator.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/NarrativeGenerator.java
rename to hapi-fhir-base/examples/src/main/java/example/NarrativeGenerator.java
diff --git a/hapi-fhir-base/src/site/example/java/example/PagingPatientProvider.java b/hapi-fhir-base/examples/src/main/java/example/PagingPatientProvider.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/PagingPatientProvider.java
rename to hapi-fhir-base/examples/src/main/java/example/PagingPatientProvider.java
diff --git a/hapi-fhir-base/src/site/example/java/example/PagingServer.java b/hapi-fhir-base/examples/src/main/java/example/PagingServer.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/PagingServer.java
rename to hapi-fhir-base/examples/src/main/java/example/PagingServer.java
diff --git a/hapi-fhir-base/src/site/example/java/example/QuickUsage.java b/hapi-fhir-base/examples/src/main/java/example/QuickUsage.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/QuickUsage.java
rename to hapi-fhir-base/examples/src/main/java/example/QuickUsage.java
diff --git a/hapi-fhir-base/src/site/example/java/example/RestfulObservationResourceProvider.java b/hapi-fhir-base/examples/src/main/java/example/RestfulObservationResourceProvider.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/RestfulObservationResourceProvider.java
rename to hapi-fhir-base/examples/src/main/java/example/RestfulObservationResourceProvider.java
diff --git a/hapi-fhir-base/src/site/example/java/example/RestfulPatientResourceProvider.java b/hapi-fhir-base/examples/src/main/java/example/RestfulPatientResourceProvider.java
similarity index 100%
rename from hapi-fhir-base/src/site/example/java/example/RestfulPatientResourceProvider.java
rename to hapi-fhir-base/examples/src/main/java/example/RestfulPatientResourceProvider.java
diff --git a/hapi-fhir-base/src/site/example/java/example/RestfulPatientResourceProviderMore.java b/hapi-fhir-base/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
similarity index 99%
rename from hapi-fhir-base/src/site/example/java/example/RestfulPatientResourceProviderMore.java
rename to hapi-fhir-base/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
index 6f4c3c1d6f8..1bb652fbafd 100644
--- a/hapi-fhir-base/src/site/example/java/example/RestfulPatientResourceProviderMore.java
+++ b/hapi-fhir-base/examples/src/main/java/example/RestfulPatientResourceProviderMore.java
@@ -19,7 +19,7 @@ import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.api.annotation.Description;
-import ca.uhn.fhir.model.api.annotation.TagListParam;
+import ca.uhn.fhir.rest.annotation.TagListParam;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
@@ -57,7 +57,6 @@ import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
-import ca.uhn.fhir.rest.client.ITestClient;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.param.CompositeParam;
@@ -78,6 +77,14 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
@SuppressWarnings("unused")
public abstract class RestfulPatientResourceProviderMore implements IResourceProvider {
+ public interface ITestClient extends IBasicClient
+ {
+
+ @Search
+ List getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theParam);
+
+ }
+
private boolean detectedVersionConflict;
private boolean conflictHappened;
private boolean couldntFindThisId;
diff --git a/hapi-fhir-base/examples/src/main/java/example/ServerMetadataExamples.java b/hapi-fhir-base/examples/src/main/java/example/ServerMetadataExamples.java
new file mode 100644
index 00000000000..d9f5621e3a8
--- /dev/null
+++ b/hapi-fhir-base/examples/src/main/java/example/ServerMetadataExamples.java
@@ -0,0 +1,56 @@
+package example;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
+import ca.uhn.fhir.model.api.Tag;
+import ca.uhn.fhir.model.api.TagList;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.model.primitive.InstantDt;
+import ca.uhn.fhir.rest.annotation.Search;
+
+public class ServerMetadataExamples {
+
+ // START SNIPPET: serverMethod
+ @Search
+ public List getAllPatients() {
+ ArrayList retVal = new ArrayList();
+
+ // Create a patient to return
+ Patient patient = new Patient();
+ retVal.add(patient);
+ patient.setId("Patient/123");
+ patient.addName().addFamily("Smith").addGiven("John");
+
+ // Create a tag list and add it to the resource
+ TagList tags = new TagList();
+ tags.addTag(Tag.HL7_ORG_FHIR_TAG, "http://foo/tag1.html", "Some tag");
+ tags.addTag(Tag.HL7_ORG_FHIR_TAG, "http://foo/tag2.html", "Another tag");
+ ResourceMetadataKeyEnum.TAG_LIST.put(patient, tags);
+
+ // Set some links (these can be provided as relative links or absolute)
+ // and the server will convert to absolute as appropriate
+ String linkAlternate = "Patient/7736";
+ ResourceMetadataKeyEnum.LINK_ALTERNATE.put(patient, linkAlternate);
+ String linkSearch = "Patient?name=smith&name=john";
+ ResourceMetadataKeyEnum.LINK_SEARCH.put(patient, linkSearch);
+
+ // Set the published and updated dates
+ InstantDt pubDate = new InstantDt("2011-02-22");
+ ResourceMetadataKeyEnum.PUBLISHED.put(patient, pubDate);
+ InstantDt updatedDate = new InstantDt("2014-07-12T11:22:27Z");
+ ResourceMetadataKeyEnum.UPDATED.put(patient, updatedDate);
+
+ // Set the resource title (note that if you are using HAPI's narrative
+ // generation capability, the narrative generator will often create
+ // useful titles automatically, and the server will create a default
+ // title if none is provided)
+ String title = "Patient John SMITH";
+ ResourceMetadataKeyEnum.TITLE.put(patient, title);
+
+ return retVal;
+ }
+ // END SNIPPET: serverMethod
+
+}
diff --git a/hapi-fhir-base/examples/src/main/java/example/TagsExamples.java b/hapi-fhir-base/examples/src/main/java/example/TagsExamples.java
new file mode 100644
index 00000000000..fd4ac010d41
--- /dev/null
+++ b/hapi-fhir-base/examples/src/main/java/example/TagsExamples.java
@@ -0,0 +1,71 @@
+package example;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
+import ca.uhn.fhir.model.api.Tag;
+import ca.uhn.fhir.model.api.TagList;
+import ca.uhn.fhir.model.dstu.resource.Patient;
+import ca.uhn.fhir.rest.annotation.Search;
+import ca.uhn.fhir.rest.client.IGenericClient;
+
+public class TagsExamples {
+
+ public static void main(String[] args) {
+ new TagsExamples().getResourceTags();
+ }
+
+ @SuppressWarnings("unused")
+ public void getResourceTags() {
+ // START SNIPPET: getResourceTags
+ IGenericClient client = new FhirContext().newRestfulGenericClient("http://fhir.healthintersections.com.au/open");
+ Patient p = client.read(Patient.class, "1");
+
+ // Retrieve the list of tags from the resource metadata
+ TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(p);
+
+ // tags may be null if no tags were read in
+ if (tags == null) {
+ System.out.println("No tags!");
+ } else {
+
+ // You may iterate over all the tags
+ for (Tag next : tags) {
+ System.out.println(next.getScheme() + " - " + next.getTerm());
+ }
+
+ // You may also get a list of tags matching a given scheme
+ List someTags = tags.getTagsWithScheme("http://hl7.org/fhir/tag");
+
+ // Or a specific tag (by scheme and term)
+ Tag specificTag = tags.getTag("http://hl7.org/fhir/tag", "http://foo");
+
+ }
+ // END SNIPPET: getResourceTags
+ }
+
+ // START SNIPPET: serverMethod
+ @Search
+ public List getAllPatients() {
+ ArrayList retVal = new ArrayList();
+
+ // Create a patient to return
+ Patient patient = new Patient();
+ patient.setId("Patient/123");
+ patient.addName().addFamily("Smith").addGiven("John");
+
+ // Create a tag list and add it to the resource
+ TagList tags = new TagList();
+ ResourceMetadataKeyEnum.TAG_LIST.put(patient, tags);
+
+ // Add some tags to the list
+ tags.addTag(Tag.HL7_ORG_FHIR_TAG, "http://foo/tag1.html", "Some tag");
+ tags.addTag(Tag.HL7_ORG_FHIR_TAG, "http://foo/tag2.html", "Another tag");
+
+ return retVal;
+ }
+ // END SNIPPET: serverMethod
+
+}
diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml
index 55aa2383028..25a1be95a15 100644
--- a/hapi-fhir-base/pom.xml
+++ b/hapi-fhir-base/pom.xml
@@ -8,10 +8,10 @@
../pom.xml
- ca.uhn.hapi.fhirhapi-fhir-basejar
- http://hl7api.sourceforge.net/hapi-fhir/
+
+ http://jamesagnew.github.io/hapi-fhir/HAPI FHIR - Core Library
@@ -20,14 +20,11 @@
git.serverscm:git:git@github.com:jamesagnew/hapi-fhir.git
-
-
-
javax.jsonjavax.json-api
diff --git a/hapi-fhir-base/src/changes/changes.xml b/hapi-fhir-base/src/changes/changes.xml
index 8ac10dd3579..70ee8f7634a 100644
--- a/hapi-fhir-base/src/changes/changes.xml
+++ b/hapi-fhir-base/src/changes/changes.xml
@@ -7,9 +7,11 @@
+
Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University
Health Network for reporting!
@@ -72,14 +74,26 @@
is "yyyy-mm-dd" anyhow, and this is correctly handled). Thanks to Jeffrey Ting of Systems Made Simple
for reporting!
-
- Server now adds a profile tag to returned results if the resource being returned
- doesn't already have one
-
Server search method for an unnamed query gets called if the client requests a named query
with the same parameter list. Thanks to Neal Acharya of University Health Network for reporting!
+
+ Category header (for tags) is correctly read in client for "read" operation
+
+
+ Transaction method in server can now have parameter type Bundle instead of
+ List<IResource>
+
+
+ HAPI parsers now use field access to get/set values instead of method accessors and mutators.
+ This should give a small performance boost.
+
+
+ JSON parser encodes resource references incorrectly, using the name "resource" instead
+ of the name "reference" for the actual reference. Thanks to
+ Ricky Nguyen for reporting and tracking down the issue!
+
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java
index 0d78457d8aa..a917d150cce 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeDeclaredChildDefinition.java
@@ -204,8 +204,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
if (values == null) {
return Collections.emptyList();
}
- @SuppressWarnings("unchecked")
- List extends IElement> retVal = (List extends IElement>) Collections.singletonList(values);
+ List extends IElement> retVal = (List extends IElement>) Collections.singletonList((IElement)values);
return retVal;
} catch (IllegalArgumentException e) {
throw new ConfigurationException("Failed to get value", e);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
index 34cb0a692d6..ae4450aab70 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
@@ -585,25 +585,37 @@ class ModelScanner {
private String scanResource(Class extends IResource> theClass, ResourceDef resourceDefinition) {
ourLog.debug("Scanning resource class: {}", theClass.getName());
+ boolean primaryNameProvider = true;
String resourceName = resourceDefinition.name();
if (isBlank(resourceName)) {
- throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name: " + theClass.getCanonicalName());
- }
-
- if (myNameToResourceDefinitions.containsKey(resourceName)) {
- if (!myNameToResourceDefinitions.get(resourceName).getImplementingClass().equals(theClass)) {
- // throw new
- // ConfigurationException("Detected duplicate element name '" +
- // resourceName + "' in types '" + theClass.getCanonicalName() +
- // "' and '"
- // +
- // myNameToResourceDefinitions.get(resourceName).getImplementingClass()
- // + "'");
- } else {
- return resourceName;
+ Class> parent = theClass.getSuperclass();
+ primaryNameProvider=false;
+ while (parent.equals(Object.class)==false && isBlank(resourceName)) {
+ ResourceDef nextDef = parent.getAnnotation(ResourceDef.class);
+ if (nextDef != null) {
+ resourceName = nextDef.name();
+ }
+ parent = parent.getSuperclass();
+ }
+ if (isBlank(resourceName)) {
+ throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name(): " + theClass.getCanonicalName() + " - This is only allowed for types that extend other resource types ");
}
}
+// if (myNameToResourceDefinitions.containsKey(resourceName)) {
+// if (!myNameToResourceDefinitions.get(resourceName).getImplementingClass().equals(theClass)) {
+// // throw new
+// // ConfigurationException("Detected duplicate element name '" +
+// // resourceName + "' in types '" + theClass.getCanonicalName() +
+// // "' and '"
+// // +
+// // myNameToResourceDefinitions.get(resourceName).getImplementingClass()
+// // + "'");
+// } else {
+// return resourceName;
+// }
+// }
+
String resourceId = resourceDefinition.id();
if (isBlank(resourceId)) {
// throw new ConfigurationException("Resource type @" +
@@ -619,10 +631,11 @@ class ModelScanner {
String profile = resourceDefinition.profile();
- RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(theClass, resourceDefinition);
+ RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(resourceName, theClass, resourceDefinition);
myClassToElementDefinitions.put(theClass, resourceDef);
- myNameToResourceDefinitions.put(resourceName, resourceDef);
-
+ if (primaryNameProvider) {
+ myNameToResourceDefinitions.put(resourceName, resourceDef);
+ }
scanCompositeElementForChildren(theClass, resourceDef);
myIdToResourceDefinition.put(resourceId, resourceDef);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java
index cf5b18f96ec..2d7d02377f6 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildChoiceDefinition.java
@@ -34,6 +34,7 @@ import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
+import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefinition {
@@ -103,6 +104,11 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
if (alternateElementName != null) {
myNameToChildDefinition.put(alternateElementName, nextDef);
}
+
+ if (IResource.class.isAssignableFrom(next)) {
+ myDatatypeToElementDefinition.put(ResourceReferenceDt.class, nextDef);
+ }
+
myDatatypeToElementDefinition.put(next, nextDef);
myDatatypeToElementName.put(next, elementName);
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java
index 62c91ceefe5..74195f4bf05 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java
@@ -60,8 +60,8 @@ public class RuntimeResourceDefinition extends BaseRuntimeElementCompositeDefini
private List mySearchParams;
private String myId;
- public RuntimeResourceDefinition(Class extends IResource> theClass, ResourceDef theResourceAnnotation) {
- super(theResourceAnnotation.name(), theClass);
+ public RuntimeResourceDefinition(String theResourceName, Class extends IResource> theClass, ResourceDef theResourceAnnotation) {
+ super(theResourceName, theClass);
myResourceProfile = theResourceAnnotation.profile();
myId = theResourceAnnotation.id();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
index 4f242e019c3..8db3a1aeba1 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
@@ -20,7 +20,7 @@ package ca.uhn.fhir.model.api;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.apache.commons.lang3.StringUtils.*;
import java.util.ArrayList;
import java.util.HashMap;
@@ -38,16 +38,12 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.server.Constants;
+import ca.uhn.fhir.util.UrlUtil;
public class Bundle extends BaseBundle /* implements IElement */{
private volatile transient Map myIdToEntries;
- //@formatter:off
- /* ****************************************************
- * NB: add any new fields to the isEmpty() method!!!
- *****************************************************/
- //@formatter:on
private List myEntries;
private StringDt myBundleId;
private StringDt myLinkBase;
@@ -60,6 +56,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
private StringDt myTitle;
private IntegerDt myTotalResults;
private InstantDt myUpdated;
+ private TagList myCategories;
/**
* Returns true if this bundle contains zero entries
@@ -69,6 +66,16 @@ public class Bundle extends BaseBundle /* implements IElement */{
return getEntries().isEmpty();
}
+ public Tag addCategory() {
+ Tag retVal = new Tag();
+ getCategories().add(retVal);
+ return retVal;
+ }
+
+ public void addCategory(Tag theTag) {
+ getCategories().add(theTag);
+ }
+
/**
* Adds and returns a new bundle entry
*/
@@ -81,12 +88,15 @@ public class Bundle extends BaseBundle /* implements IElement */{
/**
* Retrieves a resource from a bundle given its logical ID.
*
- * Important usage notes: This method ignores base URLs (so passing in an ID of http://foo/Patient/123 will return a resource if it has the logical ID of
- * http://bar/Patient/123. Also, this method is intended to be used for bundles which have already been populated. It will cache its results for fast performance, but that means that
- * modifications to the bundle after this method is called may not be accurately reflected.
+ * Important usage notes: This method ignores base URLs (so passing in an ID of
+ * http://foo/Patient/123 will return a resource if it has the logical ID of
+ * http://bar/Patient/123. Also, this method is intended to be used for bundles which have already been
+ * populated. It will cache its results for fast performance, but that means that modifications to the bundle after
+ * this method is called may not be accurately reflected.
*
*
- * @param theId The resource ID
+ * @param theId
+ * The resource ID
* @return Returns the resource with the given ID, or null if none is found
*/
public IResource getResourceById(IdDt theId) {
@@ -103,31 +113,43 @@ public class Bundle extends BaseBundle /* implements IElement */{
return map.get(theId.toUnqualified());
}
-// public static void main(String[] args) {
-//
-// FhirContext ctx = new FhirContext();
-// String txt = "\n" +
-// " \n" +
-// " \n" +
-// " \n" +
-// " \n" +
-// " \n" +
-// "
\n" +
+ // " \n" +
+ // " \n" +
+ // " \n" +
+ // " \n" +
+ // "";
+ //
+ // IGenericClient c = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/base");
+ // c.registerInterceptor(new LoggingInterceptor(true));
+ // c.update().resource(txt).withId("1665").execute();
+ // }
+ //
+
+ public TagList getCategories() {
+ if (myCategories == null) {
+ myCategories = new TagList();
+ }
+ return myCategories;
+ }
+
+ public void setCategories(TagList theCategories) {
+ myCategories = theCategories;
+ }
+
public List getEntries() {
if (myEntries == null) {
myEntries = new ArrayList();
@@ -263,14 +285,12 @@ public class Bundle extends BaseBundle /* implements IElement */{
*
* @param theResource
* The resource to add
- * @return Returns the newly created bundle entry that was added to the bundle
+ * @return Returns the newly created bundle entry that was added to the bundle
*/
public BundleEntry addResource(IResource theResource, FhirContext theContext, String theServerBase) {
BundleEntry entry = addEntry();
entry.setResource(theResource);
- entry.setResource(theResource);
-
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
String title = ResourceMetadataKeyEnum.TITLE.get(theResource);
@@ -279,7 +299,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
} else {
entry.getTitle().setValue(def.getName() + " " + StringUtils.defaultString(theResource.getId().getValue(), "(no ID)"));
}
-
+
if (theResource.getId() != null && StringUtils.isNotBlank(theResource.getId().getValue())) {
StringBuilder b = new StringBuilder();
@@ -311,7 +331,25 @@ public class Bundle extends BaseBundle /* implements IElement */{
String qualifiedId = b.toString();
entry.getLinkSelf().setValue(qualifiedId);
-
+
+ // String resourceType = theContext.getResourceDefinition(theResource).getName();
+
+ String linkSearch = ResourceMetadataKeyEnum.LINK_SEARCH.get(theResource);
+ if (isNotBlank(linkSearch)) {
+ if (!UrlUtil.isAbsolute(linkSearch)) {
+ linkSearch = (theServerBase + "/" + linkSearch);
+ }
+ entry.getLinkSearch().setValue(linkSearch);
+ }
+
+ String linkAlternate = ResourceMetadataKeyEnum.LINK_ALTERNATE.get(theResource);
+ if (isNotBlank(linkAlternate)) {
+ if (!UrlUtil.isAbsolute(linkAlternate)) {
+ linkSearch = (theServerBase + "/" + linkAlternate);
+ }
+ entry.getLinkAlternate().setValue(linkSearch);
+ }
+
}
InstantDt published = ResourceMetadataKeyEnum.PUBLISHED.get(theResource);
@@ -346,9 +384,9 @@ public class Bundle extends BaseBundle /* implements IElement */{
return entry;
}
- public static Bundle withResources(ArrayList theUploadBundle, FhirContext theContext, String theServerBase) {
+ public static Bundle withResources(List theResources, FhirContext theContext, String theServerBase) {
Bundle retVal = new Bundle();
- for (IResource next : theUploadBundle) {
+ for (IResource next : theResources) {
retVal.addResource(next, theContext, theServerBase);
}
return retVal;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ResourceMetadataKeyEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ResourceMetadataKeyEnum.java
index d73cf580001..3997550f8ca 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ResourceMetadataKeyEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ResourceMetadataKeyEnum.java
@@ -197,6 +197,52 @@ public abstract class ResourceMetadataKeyEnum {
}
};
+ /**
+ * If present and populated with a string, provides the "search link" (the link
+ * element in the bundle entry with rel="search"). Server implementations
+ * may populate this with a complete URL, in which case the URL will be
+ * placed as-is in the bundle. They may alternately specify a
+ * resource relative URL (e.g. "Patient?name=tester") in which case the
+ * server will convert this to an absolute URL at runtime.
+ *
+ * Values for this key are of type {@link String}
+ *
+ */
+ public static final ResourceMetadataKeyEnum LINK_SEARCH = new ResourceMetadataKeyEnum("LINK_SEARCH") {
+ @Override
+ public String get(IResource theResource) {
+ return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_SEARCH);
+ }
+
+ @Override
+ public void put(IResource theResource, String theObject) {
+ theResource.getResourceMetadata().put(LINK_SEARCH, theObject);
+ }
+ };
+
+ /**
+ * If present and populated with a string, provides the "alternate link" (the link
+ * element in the bundle entry with rel="alternate"). Server implementations
+ * may populate this with a complete URL, in which case the URL will be
+ * placed as-is in the bundle. They may alternately specify a
+ * resource relative URL (e.g. "Patient/1243") in which case the
+ * server will convert this to an absolute URL at runtime.
+ *
+ * Values for this key are of type {@link String}
+ *
+ */
+ public static final ResourceMetadataKeyEnum LINK_ALTERNATE = new ResourceMetadataKeyEnum("LINK_ALTERNATE") {
+ @Override
+ public String get(IResource theResource) {
+ return getStringFromMetadataOrNullIfNone(theResource.getResourceMetadata(), LINK_ALTERNATE);
+ }
+
+ @Override
+ public void put(IResource theResource, String theObject) {
+ theResource.getResourceMetadata().put(LINK_ALTERNATE, theObject);
+ }
+ };
+
private final String myValue;
public ResourceMetadataKeyEnum(String theValue) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Tag.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Tag.java
index cebbf68d328..a238d27b832 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Tag.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Tag.java
@@ -35,6 +35,18 @@ public class Tag extends BaseElement implements IElement {
*/
public static final String HL7_ORG_FHIR_TAG = "http://hl7.org/fhir/tag";
+ /**
+ * Convenience constant containing the "http://hl7.org/fhir/tag/security" scheme
+ * value
+ */
+ public static final String HL7_ORG_SECURITY_TAG = "http://hl7.org/fhir/tag/security";
+
+ /**
+ * Convenience constant containing the "http://hl7.org/fhir/tag/profile" scheme
+ * value
+ */
+ public static final String HL7_ORG_PROFILE_TAG = "http://hl7.org/fhir/tag/profile";
+
public static final String ATTR_TERM = "term";
public static final String ATTR_LABEL = "label";
public static final String ATTR_SCHEME = "scheme";
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
index 9818c57a9c7..458540976bb 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
@@ -21,6 +21,7 @@ package ca.uhn.fhir.model.api;
*/
import java.util.ArrayList;
+import java.util.List;
public class TagList extends ArrayList {
@@ -48,7 +49,7 @@ public class TagList extends ArrayList {
return null;
}
- public ArrayList getTagsWithScheme(String theScheme) {
+ public List getTagsWithScheme(String theScheme) {
ArrayList retVal = new ArrayList();
for (Tag next : this) {
if (theScheme.equals(next.getScheme())) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java
index 6d9668de911..817b981b01f 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/annotation/ResourceDef.java
@@ -35,7 +35,7 @@ public @interface ResourceDef {
/**
* The name of the resource (e.g. "Patient" or "DiagnosticReport")
*/
- String name();
+ String name() default "";
/**
* Not currently used
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
index dc36af0bc05..1654f7a3721 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
@@ -34,6 +34,7 @@ import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.Constants;
+import ca.uhn.fhir.util.UrlUtil;
/**
* Represents the FHIR ID type. This is the actual resource ID, meaning the ID that will be used in RESTful URLs,
@@ -253,6 +254,14 @@ public class IdDt extends BasePrimitive {
return isNotBlank(getVersionIdPart());
}
+ /**
+ * Returns true if this ID contains an absolute URL (in other words, a URL starting with "http://" or
+ * "https://"
+ */
+ public boolean isAbsolute() {
+ return UrlUtil.isAbsolute(getValue());
+ }
+
/**
* Returns true if the unqualified ID is a valid {@link Long} value (in other words, it consists only
* of digits)
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java
index afa06b84f47..27807d57331 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/view/ViewGenerator.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.model.view;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 University Health Network
+ * %%
+ * 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.
+ * #L%
+ */
+
import java.util.List;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
index fae9a39f18a..79490dcef92 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
@@ -166,6 +166,8 @@ public class JsonParser extends BaseParser implements IParser {
if (linkStarted) {
eventWriter.writeEnd();
}
+
+ writeCategories(eventWriter, theBundle.getCategories());
writeOptionalTagWithTextNode(eventWriter, "totalResults", theBundle.getTotalResults());
@@ -193,17 +195,7 @@ public class JsonParser extends BaseParser implements IParser {
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
- if (nextEntry.getCategories() != null && nextEntry.getCategories().size() > 0) {
- eventWriter.writeStartArray("category");
- for (Tag next : nextEntry.getCategories()) {
- eventWriter.writeStartObject();
- eventWriter.write("term", defaultString(next.getTerm()));
- eventWriter.write("label", defaultString(next.getLabel()));
- eventWriter.write("scheme", defaultString(next.getScheme()));
- eventWriter.writeEnd();
- }
- eventWriter.writeEnd();
- }
+ writeCategories(eventWriter, nextEntry.getCategories());
writeAuthor(nextEntry, eventWriter);
@@ -221,6 +213,20 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.flush();
}
+ private void writeCategories(JsonGenerator eventWriter, TagList categories) {
+ if (categories != null && categories.size() > 0) {
+ eventWriter.writeStartArray("category");
+ for (Tag next : categories) {
+ eventWriter.writeStartObject();
+ eventWriter.write("term", defaultString(next.getTerm()));
+ eventWriter.write("label", defaultString(next.getLabel()));
+ eventWriter.write("scheme", defaultString(next.getScheme()));
+ eventWriter.writeEnd();
+ }
+ eventWriter.writeEnd();
+ }
+ }
+
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition> theChildDef,
String theChildName) throws IOException {
@@ -291,10 +297,10 @@ public class JsonParser extends BaseParser implements IParser {
}
if (StringUtils.isNotBlank(reference)) {
- theWriter.write("resource", reference);
+ theWriter.write(XmlParser.RESREF_REFERENCE, reference);
}
if (referenceDt.getDisplay().isEmpty() == false) {
- theWriter.write("display", referenceDt.getDisplay().getValueAsString());
+ theWriter.write(XmlParser.RESREF_DISPLAY, referenceDt.getDisplay().getValueAsString());
}
theWriter.writeEnd();
break;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
index 3018c2f7f6e..a78a5679161 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
@@ -20,8 +20,7 @@ package ca.uhn.fhir.parser;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.apache.commons.lang3.StringUtils.*;
import java.util.ArrayList;
import java.util.HashMap;
@@ -67,6 +66,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.rest.server.Constants;
+import ca.uhn.fhir.util.IModelVisitor;
class ParserState {
@@ -474,6 +474,12 @@ class ParserState {
metadata.put(ResourceMetadataKeyEnum.VERSION_ID, linkSelf);
}
}
+ if (!myEntry.getLinkAlternate().isEmpty()) {
+ ResourceMetadataKeyEnum.LINK_ALTERNATE.put(myEntry.getResource(), myEntry.getLinkAlternate().getValue());
+ }
+ if (!myEntry.getLinkSearch().isEmpty()) {
+ ResourceMetadataKeyEnum.LINK_SEARCH.put(myEntry.getResource(), myEntry.getLinkSearch().getValue());
+ }
}
@@ -622,6 +628,8 @@ class ParserState {
push(new AtomPrimitiveState(myInstance.getUpdated()));
} else if ("author".equals(theLocalPart)) {
push(new AtomAuthorState(myInstance));
+ } else if ("category".equals(theLocalPart)) {
+ push(new AtomCategoryState(myInstance.getCategories().addTag()));
} else if ("deleted-entry".equals(theLocalPart) && verifyNamespace(XmlParser.TOMBSTONES_NS, theNamespaceURI)) {
push(new AtomDeletedEntryState(myInstance, myResourceType));
} else {
@@ -902,7 +910,7 @@ class ParserState {
public void attributeValue(String theName, String theValue) throws DataFormatException {
if ("id".equals(theName)) {
if (myInstance instanceof IIdentifiableElement) {
- ((IIdentifiableElement) myInstance).setId(new IdDt(theValue));
+ ((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
} else if (myInstance instanceof IResource) {
((IResource) myInstance).setId(new IdDt(theValue));
}
@@ -1249,20 +1257,32 @@ class ParserState {
myObject = (T) myInstance;
}
- for (ResourceReferenceDt nextRef : myResourceReferences) {
- String ref = nextRef.getReference().getValue();
- if (isNotBlank(ref)) {
- if (ref.startsWith("#")) {
- IResource target = myContainedResources.get(ref.substring(1));
- if (target != null) {
- nextRef.setResource(target);
- } else {
- ourLog.warn("Resource contains unknown local ref: " + ref);
+ myContext.newTerser().visit(myInstance, new IModelVisitor() {
+
+ @Override
+ public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition, ExtensionDt theNextExt) {
+ acceptElement(theNextExt.getValue(), null, null);
+ }
+
+ @Override
+ public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition) {
+ if (theElement instanceof ResourceReferenceDt) {
+ ResourceReferenceDt nextRef = (ResourceReferenceDt)theElement;
+ String ref = nextRef.getReference().getValue();
+ if (isNotBlank(ref)) {
+ if (ref.startsWith("#")) {
+ IResource target = myContainedResources.get(ref.substring(1));
+ if (target != null) {
+ nextRef.setResource(target);
+ } else {
+ ourLog.warn("Resource contains unknown local ref: " + ref);
+ }
+ }
}
}
}
- }
-
+ });
+
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
index 571dd838bc8..071ce0b5ff5 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
@@ -80,6 +80,8 @@ import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
public class XmlParser extends BaseParser implements IParser {
+ static final String RESREF_DISPLAY = "display";
+ static final String RESREF_REFERENCE = "reference";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
static final String FHIR_NS = "http://hl7.org/fhir";
@@ -144,6 +146,8 @@ public class XmlParser extends BaseParser implements IParser {
eventWriter.writeEndElement();
}
+ writeCategories(eventWriter, theBundle.getCategories());
+
for (BundleEntry nextEntry : theBundle.getEntries()) {
boolean deleted = false;
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
@@ -182,15 +186,7 @@ public class XmlParser extends BaseParser implements IParser {
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
- if (nextEntry.getCategories() != null) {
- for (Tag next : nextEntry.getCategories()) {
- eventWriter.writeStartElement("category");
- eventWriter.writeAttribute("term", defaultString(next.getTerm()));
- eventWriter.writeAttribute("label", defaultString(next.getLabel()));
- eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
- eventWriter.writeEndElement();
- }
- }
+ writeCategories(eventWriter, nextEntry.getCategories());
if (!nextEntry.getLinkSelf().isEmpty()) {
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
@@ -224,6 +220,18 @@ public class XmlParser extends BaseParser implements IParser {
}
}
+ private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
+ if (categories != null) {
+ for (Tag next : categories) {
+ eventWriter.writeStartElement("category");
+ eventWriter.writeAttribute("term", defaultString(next.getTerm()));
+ eventWriter.writeAttribute("label", defaultString(next.getLabel()));
+ eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
+ eventWriter.writeEndElement();
+ }
+ }
+ }
+
@Override
public String encodeResourceToString(IResource theResource) throws DataFormatException {
if (theResource == null) {
@@ -550,12 +558,12 @@ public class XmlParser extends BaseParser implements IParser {
// }
if (!(theRef.getDisplay().isEmpty())) {
- theEventWriter.writeStartElement("display");
+ theEventWriter.writeStartElement(RESREF_DISPLAY);
theEventWriter.writeAttribute("value", theRef.getDisplay().getValue());
theEventWriter.writeEndElement();
}
if (StringUtils.isNotBlank(reference)) {
- theEventWriter.writeStartElement("reference");
+ theEventWriter.writeStartElement(RESREF_REFERENCE);
theEventWriter.writeAttribute("value", reference);
theEventWriter.writeEndElement();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TransactionParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TransactionParam.java
index 63c854f7a08..415562a5723 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TransactionParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/annotation/TransactionParam.java
@@ -24,7 +24,15 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.util.List;
+import ca.uhn.fhir.model.api.Bundle;
+
+/**
+ * Parameter annotation for the "transaction" operation. The parameter annotated with this
+ * annotation must be either of type {@link Bundle} or of type
+ * {@link List}<IResource>
+ */
@Target(value=ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionParam {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
index cc8028d595f..cdabdedb088 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
@@ -20,8 +20,6 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.isBlank;
-
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
@@ -39,7 +37,6 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
-import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
@@ -54,9 +51,7 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
- private static final String LABEL = "label=\"";
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
- private static final String SCHEME = "scheme=\"";
private boolean myReturnVoid;
@@ -118,7 +113,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
String nextTagComplete = enumeration.nextElement();
- parseTagValue(tagList, nextTagComplete);
+ MethodUtil.parseTagValue(tagList, nextTagComplete);
}
if (tagList.isEmpty() == false) {
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
@@ -218,19 +213,25 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding 0 && theBuffer.charAt(0) == ' ') {
- theBuffer.deleteCharAt(0);
- }
-
- while (theBuffer.length() > 0) {
- boolean foundSomething = false;
- if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
- int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
- scheme = theBuffer.substring(SCHEME.length(), closeIdx);
- theBuffer.delete(0, closeIdx + 1);
- foundSomething = true;
- }
- if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
- int closeIdx = theBuffer.indexOf("\"", LABEL.length());
- label = theBuffer.substring(LABEL.length(), closeIdx);
- theBuffer.delete(0, closeIdx + 1);
- foundSomething = true;
- }
- // TODO: support enc2231-string as described in
- // http://tools.ietf.org/html/draft-johnston-http-category-header-02
- // TODO: support multiple tags in one header as described in
- // http://hl7.org/implement/standards/fhir/http.html#tags
-
- while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
- theBuffer.deleteCharAt(0);
- }
-
- if (!foundSomething) {
- break;
- }
- }
-
- if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
- theBuffer.deleteCharAt(0);
- while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
- theBuffer.deleteCharAt(0);
- }
- theTagList.add(new Tag(scheme, term, label));
- parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
- } else {
- theTagList.add(new Tag(scheme, term, label));
- }
-
- if (theBuffer.length() > 0) {
- ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
- }
-
- }
-
protected abstract void addParametersForServerRequest(Request theRequest, Object[] theParams);
/**
@@ -366,6 +274,16 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding provideAllowableRequestTypes();
/**
@@ -425,4 +343,5 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding categoryHeaders = theHeaders.get(Constants.HEADER_CATEGORY_LC);
+ if (categoryHeaders != null && categoryHeaders.size() > 0 && StringUtils.isNotBlank(categoryHeaders.get(0))) {
+ TagList tagList = new TagList();
+ for (String header : categoryHeaders) {
+ parseTagValue(tagList, header);
+ }
+ ResourceMetadataKeyEnum.TAG_LIST.put(resource, tagList);
+ }
}
+ public static void parseTagValue(TagList tagList, String nextTagComplete) {
+ StringBuilder next = new StringBuilder(nextTagComplete);
+ parseTagValue(tagList, nextTagComplete, next);
+ }
+
+ private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
+ int firstSemicolon = theBuffer.indexOf(";");
+ int deleteTo;
+ if (firstSemicolon == -1) {
+ firstSemicolon = theBuffer.indexOf(",");
+ if (firstSemicolon == -1) {
+ firstSemicolon = theBuffer.length();
+ deleteTo = theBuffer.length();
+ } else {
+ deleteTo = firstSemicolon;
+ }
+ } else {
+ deleteTo = firstSemicolon + 1;
+ }
+
+ String term = theBuffer.substring(0, firstSemicolon);
+ String scheme = null;
+ String label = null;
+ if (isBlank(term)) {
+ return;
+ }
+
+ theBuffer.delete(0, deleteTo);
+ while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
+ theBuffer.deleteCharAt(0);
+ }
+
+ while (theBuffer.length() > 0) {
+ boolean foundSomething = false;
+ if (theBuffer.length() > SCHEME.length() && theBuffer.substring(0, SCHEME.length()).equals(SCHEME)) {
+ int closeIdx = theBuffer.indexOf("\"", SCHEME.length());
+ scheme = theBuffer.substring(SCHEME.length(), closeIdx);
+ theBuffer.delete(0, closeIdx + 1);
+ foundSomething = true;
+ }
+ if (theBuffer.length() > LABEL.length() && theBuffer.substring(0, LABEL.length()).equals(LABEL)) {
+ int closeIdx = theBuffer.indexOf("\"", LABEL.length());
+ label = theBuffer.substring(LABEL.length(), closeIdx);
+ theBuffer.delete(0, closeIdx + 1);
+ foundSomething = true;
+ }
+ // TODO: support enc2231-string as described in
+ // http://tools.ietf.org/html/draft-johnston-http-category-header-02
+ // TODO: support multiple tags in one header as described in
+ // http://hl7.org/implement/standards/fhir/http.html#tags
+
+ while (theBuffer.length() > 0 && (theBuffer.charAt(0) == ' ' || theBuffer.charAt(0) == ';')) {
+ theBuffer.deleteCharAt(0);
+ }
+
+ if (!foundSomething) {
+ break;
+ }
+ }
+
+ if (theBuffer.length() > 0 && theBuffer.charAt(0) == ',') {
+ theBuffer.deleteCharAt(0);
+ while (theBuffer.length() > 0 && theBuffer.charAt(0) == ' ') {
+ theBuffer.deleteCharAt(0);
+ }
+ theTagList.add(new Tag(scheme, term, label));
+ parseTagValue(theTagList, theCompleteHeaderValue, theBuffer);
+ } else {
+ theTagList.add(new Tag(scheme, term, label));
+ }
+
+ if (theBuffer.length() > 0) {
+ ourLog.warn("Ignoring extra text at the end of " + Constants.HEADER_CATEGORY + " tag '" + theBuffer.toString() + "' - Complete tag value was: " + theCompleteHeaderValue);
+ }
+
+ }
+
+
static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
index e95f3f4cc6a..9f04d473a4c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionMethodBinding.java
@@ -20,11 +20,11 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.lang.reflect.Method;
-import java.util.ArrayList;
+import java.util.IdentityHashMap;
import java.util.List;
import ca.uhn.fhir.context.ConfigurationException;
@@ -52,9 +52,9 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
public TransactionMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
super(null, theMethod, theConetxt, theProvider);
-
+
myTransactionParamIndex = -1;
- int index=0;
+ int index = 0;
for (IParameter next : getParameters()) {
if (next instanceof TransactionParamBinder) {
myTransactionParamIndex = index;
@@ -62,7 +62,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
index++;
}
- if (myTransactionParamIndex==-1) {
+ if (myTransactionParamIndex == -1) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with the @" + TransactionParam.class + " annotation");
}
}
@@ -72,7 +72,6 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
return RestfulOperationSystemEnum.TRANSACTION;
}
-
@Override
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
if (theRequest.getRequestType() != RequestType.POST) {
@@ -95,16 +94,24 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@SuppressWarnings("unchecked")
@Override
public IBundleProvider invokeServer(Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
- List resources = (List) theMethodParams[myTransactionParamIndex];
-
- List oldIds= new ArrayList();
- for (IResource next : resources) {
- oldIds.add(next.getId());
+ // Grab the IDs of all of the resources in the transaction
+ List resources;
+ if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
+ resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
+ } else {
+ resources = (List) theMethodParams[myTransactionParamIndex];
}
- Object response= invokeServerMethod(theMethodParams);
+ IdentityHashMap oldIds = new IdentityHashMap();
+ for (IResource next : resources) {
+ oldIds.put(next, next.getId());
+ }
+
+ // Call the server implementation method
+ Object response = invokeServerMethod(theMethodParams);
IBundleProvider retVal = toResourceList(response);
-
+
+ /*
int offset = 0;
if (retVal.size() != resources.size()) {
if (retVal.size() > 0 && retVal.getResources(0, 1).get(0) instanceof OperationOutcome) {
@@ -113,24 +120,30 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
throw new InternalErrorException("Transaction bundle contained " + resources.size() + " entries, but server method response contained " + retVal.size() + " entries (must be the same)");
}
}
+ */
- List retResources = retVal.getResources(offset, retVal.size());
- for (int i =0; i < resources.size(); i++) {
- IdDt oldId = oldIds.get(i);
+ List retResources = retVal.getResources(0, retVal.size());
+ for (int i = 0; i < retResources.size(); i++) {
+ IdDt oldId = oldIds.get(retResources.get(i));
IResource newRes = retResources.get(i);
if (newRes.getId() == null || newRes.getId().isEmpty()) {
- throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)");
+ if (!(newRes instanceof OperationOutcome)) {
+ throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)");
+ }
}
-
+
if (oldId != null && !oldId.isEmpty()) {
if (!oldId.equals(newRes.getId())) {
newRes.getResourceMetadata().put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
}
}
}
-
+
return retVal;
- }
+
+
+
+ }
@Override
protected Object parseRequestObject(Request theRequest) throws IOException {
@@ -147,11 +160,15 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@Override
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
- @SuppressWarnings("unchecked")
- List resources = (List) theArgs[myTransactionParamIndex];
FhirContext context = getContext();
-
- return createTransactionInvocation(resources, context);
+ if (theArgs[myTransactionParamIndex] instanceof Bundle) {
+ Bundle bundle = (Bundle) theArgs[myTransactionParamIndex];
+ return createTransactionInvocation(bundle, context);
+ } else {
+ @SuppressWarnings("unchecked")
+ List resources = (List) theArgs[myTransactionParamIndex];
+ return createTransactionInvocation(resources, context);
+ }
}
public static BaseHttpClientInvocation createTransactionInvocation(List theResources, FhirContext theContext) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionParamBinder.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionParamBinder.java
index 0f4ef87a5c9..22e23b9d6e2 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionParamBinder.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/TransactionParamBinder.java
@@ -38,40 +38,56 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class TransactionParamBinder implements IParameter {
+ private boolean myParamIsBundle;
+
public TransactionParamBinder() {
}
-
+
@Override
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, BaseHttpClientInvocation theClientInvocation) throws InternalErrorException {
// TODO Auto-generated method stub
-
+
}
@Override
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
Bundle resource = (Bundle) theRequestContents;
-
+ if (myParamIsBundle) {
+ return resource;
+ }
+
ArrayList retVal = new ArrayList();
for (BundleEntry next : resource.getEntries()) {
if (next.getResource() != null) {
retVal.add(next.getResource());
}
}
-
+
return retVal;
}
@Override
public void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType) {
if (theOuterCollectionType != null) {
- throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but can not be a collection of collections");
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but can not be a collection of collections");
}
- if (theInnerCollectionType.equals(List.class)==false) {
- throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()+">");
- }
- if (theParameterType.equals(IResource.class)==false) {
- throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()+">");
+ if (theParameterType.equals(Bundle.class)) {
+ myParamIsBundle=true;
+ if (theInnerCollectionType!=null) {
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()
+ + "> or Bundle");
+ }
+ } else {
+ myParamIsBundle=false;
+ if (theInnerCollectionType.equals(List.class) == false) {
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()
+ + "> or Bundle");
+ }
+ if (theParameterType.equals(IResource.class) == false) {
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()
+ + "> or Bundle");
+ }
}
}
-
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
index 7b3a1cfae2e..91b44f85f8a 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.rest.param;
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 University Health Network
+ * %%
+ * 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.
+ * #L%
+ */
+
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.server.Constants;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index 2e71ec2d5e7..24b414793eb 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -48,6 +48,7 @@ public class Constants {
public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
public static final String HEADER_AUTHORIZATION = "Authorization";
public static final String HEADER_CATEGORY = "Category";
+ public static final String HEADER_CATEGORY_LC = HEADER_CATEGORY.toLowerCase();
public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
@@ -97,8 +98,6 @@ public class Constants {
public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
public static final String URL_TOKEN_HISTORY = "_history";
- public static final String TAG_SCHEME_PROFILE = "http://hl7.org/fhir/tag/profile ";
-
static {
Map valToEncoding = new HashMap();
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
index 6632894eced..ac48f1eaca4 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
@@ -844,46 +844,48 @@ public class RestfulServer extends HttpServlet {
}
}
}
-
+
// Linked resources may themselves have linked resources
references = new ArrayList();
for (IResource iResource : addedResourcesThisPass) {
List newReferences = theContext.newTerser().getAllPopulatedChildElementsOfType(iResource, ResourceReferenceDt.class);
references.addAll(newReferences);
}
-
+
addedResources.addAll(addedResourcesThisPass);
-
+
} while (references.isEmpty() == false);
-
- BundleEntry entry = bundle.addResource(next, theContext, theServerBase);
- addProfileToBundleEntry(theContext, next, entry);
-
+
+ bundle.addResource(next, theContext, theServerBase);
+// addProfileToBundleEntry(theContext, next, entry);
+
}
/*
* Actually add the resources to the bundle
*/
for (IResource next : addedResources) {
- BundleEntry entry = bundle.addResource(next, theContext, theServerBase);
- addProfileToBundleEntry(theContext, next, entry);
+ bundle.addResource(next, theContext, theServerBase);
+// addProfileToBundleEntry(theContext, next, entry);
}
bundle.getTotalResults().setValue(theTotalResults);
return bundle;
}
+ /*
private static void addProfileToBundleEntry(FhirContext theContext, IResource next, BundleEntry entry) {
- ArrayList profileTags = entry.getCategories().getTagsWithScheme(Constants.TAG_SCHEME_PROFILE);
+ List profileTags = entry.getCategories().getTagsWithScheme(Tag.HL7_ORG_PROFILE_TAG);
if (profileTags.isEmpty()) {
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(next);
String profile = nextDef.getResourceProfile();
if (isNotBlank(profile)) {
- entry.addCategory(new Tag(Constants.TAG_SCHEME_PROFILE, profile, null));
+ entry.addCategory(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
}
}
}
-
+ */
+
public static String createPagingLink(String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
StringBuilder b = new StringBuilder();
b.append(theServerBase);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/AuthenticationException.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/AuthenticationException.java
index c863964832e..ca8a931e68c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/AuthenticationException.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/AuthenticationException.java
@@ -1,7 +1,5 @@
package ca.uhn.fhir.rest.server.exceptions;
-import java.text.ParseException;
-
import ca.uhn.fhir.rest.server.Constants;
/*
@@ -41,7 +39,7 @@ public class AuthenticationException extends BaseServerResponseException {
super(STATUS_CODE, theMessage);
}
- public AuthenticationException(String theMessage, ParseException theCause) {
+ public AuthenticationException(String theMessage, Throwable theCause) {
super(STATUS_CODE, theMessage, theCause);
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.java
index c8a1dd95ea8..4725ef95c2b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.java
@@ -27,9 +27,8 @@ import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
*/
/**
- * Base class for RESTful client and server exceptions. RESTful client methods
- * will only throw exceptions which are subclasses of this exception type, and
- * RESTful server methods should also only call subclasses of this exception
+ * Base class for RESTful client and server exceptions. RESTful client methods will only throw exceptions which are
+ * subclasses of this exception type, and RESTful server methods should also only call subclasses of this exception
* type.
*/
public abstract class BaseServerResponseException extends RuntimeException {
@@ -50,10 +49,8 @@ public abstract class BaseServerResponseException extends RuntimeException {
}
private final OperationOutcome myOperationOutcome;
-
private String myResponseBody;
private String myResponseMimeType;
-
private int myStatusCode;
/**
@@ -77,6 +74,9 @@ public abstract class BaseServerResponseException extends RuntimeException {
* The HTTP status code corresponding to this problem
* @param theMessage
* The message
+ * @param theOperationOutcome
+ * An OperationOutcome resource to return to the calling client (in a server) or the OperationOutcome
+ * that was returned from the server (in a client)
*/
public BaseServerResponseException(int theStatusCode, String theMessage, OperationOutcome theOperationOutcome) {
super(theMessage);
@@ -100,6 +100,25 @@ public abstract class BaseServerResponseException extends RuntimeException {
myOperationOutcome = null;
}
+ /**
+ * Constructor
+ *
+ * @param theStatusCode
+ * The HTTP status code corresponding to this problem
+ * @param theMessage
+ * The message
+ * @param theCause
+ * The underlying cause exception
+ * @param theOperationOutcome
+ * An OperationOutcome resource to return to the calling client (in a server) or the OperationOutcome
+ * that was returned from the server (in a client)
+ */
+ public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause, OperationOutcome theOperationOutcome) {
+ super(theMessage, theCause);
+ myStatusCode = theStatusCode;
+ myOperationOutcome = theOperationOutcome;
+ }
+
/**
* Constructor
*
@@ -115,17 +134,32 @@ public abstract class BaseServerResponseException extends RuntimeException {
}
/**
- * Returns the {@link OperationOutcome} resource if any which was supplied
- * in the response, or null
+ * Constructor
+ *
+ * @param theStatusCode
+ * The HTTP status code corresponding to this problem
+ * @param theCause
+ * The underlying cause exception
+ * @param theOperationOutcome
+ * An OperationOutcome resource to return to the calling client (in a server) or the OperationOutcome
+ * that was returned from the server (in a client)
+ */
+ public BaseServerResponseException(int theStatusCode, Throwable theCause, OperationOutcome theOperationOutcome) {
+ super(theCause.toString(), theCause);
+ myStatusCode = theStatusCode;
+ myOperationOutcome = theOperationOutcome;
+ }
+
+ /**
+ * Returns the {@link OperationOutcome} resource if any which was supplied in the response, or null
*/
public OperationOutcome getOperationOutcome() {
return myOperationOutcome;
}
/**
- * In a RESTful client, this method will be populated with the body of the
- * HTTP respone if one was provided by the server, or null
- * otherwise.
+ * In a RESTful client, this method will be populated with the body of the HTTP respone if one was provided by the
+ * server, or null otherwise.
*
* In a restful server, this method is currently ignored.
*
@@ -135,8 +169,8 @@ public abstract class BaseServerResponseException extends RuntimeException {
}
/**
- * In a RESTful client, this method will be populated with the HTTP status
- * code that was returned with the HTTP response.
+ * In a RESTful client, this method will be populated with the HTTP status code that was returned with the HTTP
+ * response.
*
* In a restful server, this method is currently ignored.
*
@@ -153,16 +187,14 @@ public abstract class BaseServerResponseException extends RuntimeException {
}
/**
- * This method is currently only called internally by HAPI, it should not be
- * called by user code.
+ * This method is currently only called internally by HAPI, it should not be called by user code.
*/
public void setResponseBody(String theResponseBody) {
myResponseBody = theResponseBody;
}
/**
- * This method is currently only called internally by HAPI, it should not be
- * called by user code.
+ * This method is currently only called internally by HAPI, it should not be called by user code.
*/
public void setResponseMimeType(String theResponseMimeType) {
myResponseMimeType = theResponseMimeType;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
index 1aa4144ff21..3557348d702 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
@@ -37,6 +37,7 @@ import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
+import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
@@ -108,31 +109,69 @@ public class FhirTerser {
}
/**
- * Returns a list containing all child elements (including the resource itself) which are non-empty
- * and are either of the exact type specified, or are a subclass of that type.
+ * Visit all elements in a given resource
+ *
+ * @param theResource The resource to visit
+ * @param theVisitor The visitor
+ */
+ public void visit(IResource theResource, IModelVisitor theVisitor) {
+ BaseRuntimeElementCompositeDefinition> def = myContext.getResourceDefinition(theResource);
+ visit(theResource, null, def, theVisitor);
+ }
+
+ /**
+ * Returns a list containing all child elements (including the resource itself) which are non-empty and are
+ * either of the exact type specified, or are a subclass of that type.
*
- * For example, specifying a type of {@link StringDt} would return all non-empty string instances within
- * the message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained resources.
- *
- * @param theResourceT The resource instance to search. Must not be null.
- * @param theType The type to search for. Must not be null.
+ * For example, specifying a type of {@link StringDt} would return all non-empty string instances within the
+ * message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained
+ * resources.
+ *
+ *
+ * @param theResourceT
+ * The resource instance to search. Must not be null.
+ * @param theType
+ * The type to search for. Must not be null.
* @return
*/
- public List getAllPopulatedChildElementsOfType(IResource theResource, Class theType) {
- ArrayList retVal = new ArrayList();
+ public List getAllPopulatedChildElementsOfType(IResource theResource, final Class theType) {
+ final ArrayList retVal = new ArrayList();
BaseRuntimeElementCompositeDefinition> def = myContext.getResourceDefinition(theResource);
- getAllChildElementsOfType(theResource, def, theType, retVal);
+ visit(theResource, null, def, new IModelVisitor() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition) {
+ if (theElement.isEmpty()) {
+ return;
+ }
+
+ if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
+ retVal.add((T) theElement);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition, ExtensionDt theNextExt) {
+ if (theType.isAssignableFrom(theNextExt.getClass())) {
+ retVal.add((T) theNextExt);
+ }
+ if (theNextExt.getValue() != null && theType.isAssignableFrom(theNextExt.getValue().getClass())) {
+ retVal.add((T) theNextExt.getValue());
+ }
+ }
+ });
return retVal;
}
- private void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition> theDefinition, Class theType, ArrayList theList) {
- if (theElement.isEmpty()) {
- return;
- }
-
- addIfCorrectType(theElement, theType, theList);
- addUndeclaredExtensions(theElement, theType, theList);
+ private void visit(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition, IModelVisitor theCallback) {
+ theCallback.acceptElement(theElement, theChildDefinition, theDefinition);
+ addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
+// if (theElement.isEmpty()) {
+// return;
+// }
+
switch (theDefinition.getChildType()) {
case PRIMITIVE_XHTML:
case PRIMITIVE_DATATYPE:
@@ -153,7 +192,9 @@ public class FhirTerser {
if (nextValue.isEmpty()) {
continue;
}
- BaseRuntimeElementDefinition> childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
+ BaseRuntimeElementDefinition> childElementDef;
+ childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
+
if (childElementDef == null) {
StringBuilder b = new StringBuilder();
b.append("Found value of type[");
@@ -171,7 +212,7 @@ public class FhirTerser {
}
throw new DataFormatException(b.toString());
}
- getAllChildElementsOfType(nextValue, childElementDef, theType, theList);
+ visit(nextValue, nextChild, childElementDef, theCallback);
}
}
}
@@ -181,7 +222,7 @@ public class FhirTerser {
ContainedDt value = (ContainedDt) theElement;
for (IResource next : value.getContainedResources()) {
BaseRuntimeElementCompositeDefinition> def = myContext.getResourceDefinition(next);
- getAllChildElementsOfType(next, def, theType, theList);
+ visit(next, null, def, theCallback);
}
break;
}
@@ -192,22 +233,14 @@ public class FhirTerser {
}
}
- private void addUndeclaredExtensions(IElement theElement, Class theType, ArrayList theList) {
+ private void addUndeclaredExtensions(IElement theElement, BaseRuntimeElementDefinition> theDefinition, BaseRuntimeChildDefinition theChildDefinition, IModelVisitor theCallback) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
- ISupportsUndeclaredExtensions elem = (ISupportsUndeclaredExtensions) theElement;
- for (ExtensionDt nextExt : elem.getUndeclaredExtensions()) {
- addIfCorrectType(nextExt, theType, theList);
- addIfCorrectType(nextExt.getValue(), theType, theList);
- addUndeclaredExtensions(nextExt, theType, theList);
+ ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
+ for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
+ theCallback.acceptUndeclaredExtension(containingElement, theChildDefinition, theDefinition, nextExt);
+ addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
}
}
}
- @SuppressWarnings("unchecked")
- private void addIfCorrectType(IElement theElement, Class theType, ArrayList theList) {
- if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
- theList.add((T) theElement);
- }
- }
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java
new file mode 100644
index 00000000000..47fd52f6757
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/IModelVisitor.java
@@ -0,0 +1,53 @@
+package ca.uhn.fhir.util;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 University Health Network
+ * %%
+ * 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.
+ * #L%
+ */
+
+import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
+import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
+import ca.uhn.fhir.model.api.ExtensionDt;
+import ca.uhn.fhir.model.api.IElement;
+import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
+
+/**
+ * @see FhirTerser#visit(ca.uhn.fhir.model.api.IResource, IModelVisitor)
+ */
+public interface IModelVisitor {
+
+ /**
+ *
+ * @param theElement
+ * @param theChildDefinition May be null if this is a root element
+ * @param theDefinition
+ */
+ void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition);
+
+ /**
+ *
+ * @param theContainingElement
+ * @param theChildDefinition May be null if this is a root element
+ * @param theDefinition
+ * @param theNextExt
+ */
+ void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition> theDefinition, ExtensionDt theNextExt);
+
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
new file mode 100644
index 00000000000..3d3eee15854
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
@@ -0,0 +1,30 @@
+package ca.uhn.fhir.util;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 University Health Network
+ * %%
+ * 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.
+ * #L%
+ */
+
+public class UrlUtil {
+
+ public static boolean isAbsolute(String theValue) {
+ String value = theValue.toLowerCase();
+ return value.startsWith("http://") || value.startsWith("https://");
+ }
+
+}
diff --git a/hapi-fhir-base/src/site/example/java/example/ClientExamples.java b/hapi-fhir-base/src/site/example/java/example/ClientExamples.java
deleted file mode 100644
index 24ce61cc761..00000000000
--- a/hapi-fhir-base/src/site/example/java/example/ClientExamples.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package example;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.rest.client.IGenericClient;
-import ca.uhn.fhir.rest.client.IRestfulClientFactory;
-import ca.uhn.fhir.rest.client.api.IBasicClient;
-import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
-import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
-import ca.uhn.fhir.rest.server.EncodingEnum;
-
-public class ClientExamples {
-
- public interface IPatientClient extends IBasicClient {
- // nothing yet
- }
-
- @SuppressWarnings("unused")
- public void createProxy() {
-//START SNIPPET: proxy
-FhirContext ctx = new FhirContext();
-ctx.getRestfulClientFactory().setProxy("example.com", 8888);
-
-IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
-//START SNIPPET: end
- }
-
- @SuppressWarnings("unused")
- public void createSecurity() {
-//START SNIPPET: security
-// Create a context and get the client factory so it can be configured
-FhirContext ctx = new FhirContext();
-IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
-
-//Create an HTTP basic auth interceptor
-String username = "foobar";
-String password = "boobear";
-BasicAuthInterceptor authInterceptor = new BasicAuthInterceptor(username, password);
-
-// Register the interceptor with your client (either style)
-IPatientClient annotationClient = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/fhir");
-annotationClient.registerInterceptor(authInterceptor);
-
-IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
-annotationClient.registerInterceptor(authInterceptor);
-//END SNIPPET: security
-}
-
-@SuppressWarnings("unused")
-public void createLogging() {
-{
-//START SNIPPET: logging
-//Create a context and get the client factory so it can be configured
-FhirContext ctx = new FhirContext();
-IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();
-
-//Create a logging interceptor
-LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
-
-// Optionally you may configure the interceptor (by default only summary info is logged)
-loggingInterceptor.setLogRequestSummary(true);
-loggingInterceptor.setLogRequestBody(true);
-
-//Register the interceptor with your client (either style)
-IPatientClient annotationClient = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/fhir");
-annotationClient.registerInterceptor(loggingInterceptor);
-
-IGenericClient genericClient = ctx.newRestfulGenericClient("http://localhost:9999/fhir");
-genericClient.registerInterceptor(loggingInterceptor);
-//END SNIPPET: logging
-}
-
-
-
-/******************************/
-{
-//START SNIPPET: clientConfig
-//Create a client
-FhirContext ctx = new FhirContext();
-IPatientClient client = ctx.newRestfulClient(IPatientClient.class, "http://localhost:9999/");
-
-// Request JSON encoding from the server (_format=json)
-client.setEncoding(EncodingEnum.JSON);
-
-// Request pretty printing from the server (_pretty=true)
-client.setPrettyPrint(true);
-//END SNIPPET: clientConfig
-}
- }
-
-}
diff --git a/hapi-fhir-base/src/site/example/java/example/CompleteExampleClient.java b/hapi-fhir-base/src/site/example/java/example/CompleteExampleClient.java
deleted file mode 100644
index dbfa386f777..00000000000
--- a/hapi-fhir-base/src/site/example/java/example/CompleteExampleClient.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package example;
-
-//START SNIPPET: client
-import java.io.IOException;
-import java.util.List;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
-import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
-import ca.uhn.fhir.model.dstu.resource.Organization;
-import ca.uhn.fhir.model.dstu.resource.Patient;
-import ca.uhn.fhir.rest.annotation.RequiredParam;
-import ca.uhn.fhir.rest.annotation.Search;
-import ca.uhn.fhir.rest.client.api.IRestfulClient;
-
-public class CompleteExampleClient {
-
- /**
- * This is a simple client interface. It can have many methods
- * for various searches but in this case it has only 1.
- */
- public static interface ClientInterface extends IRestfulClient
- {
-
- /**
- * This is translated into a URL similar to the following:
- * http://fhir.healthintersections.com.au/open/Patient?identifier=urn:oid:1.2.36.146.595.217.0.1%7C12345
- */
- @Search
- List findPatientsForMrn(@RequiredParam(name=Patient.SP_IDENTIFIER) IdentifierDt theIdentifier);
-
- }
-
- /**
- * The main method here will directly call an open FHIR server
- * and retrieve a list of resources matching a given criteria,
- * then load a linked resource.
- */
- public static void main(String[] args) throws IOException {
-
- // Create a client factory
- FhirContext ctx = new FhirContext();
-
- //Create the client
- String serverBase = "http://fhir.healthintersections.com.au/open";
- ClientInterface client = ctx.newRestfulClient(ClientInterface.class, serverBase);
-
- // Invoke the client to search for patient
- List patients = client.findPatientsForMrn(new IdentifierDt("urn:oid:1.2.36.146.595.217.0.1", "12345"));
-
- System.out.println("Found "+ patients.size() + " patients");
-
- // Print a value from the loaded resource
- Patient patient = patients.get(0);
- System.out.println("Patient Last Name: " + patient.getName().get(0).getFamily().get(0).getValue());
-
- // Load a referenced resource
- ResourceReferenceDt managingRef = patient.getManagingOrganization();
- Organization org = (Organization) managingRef.loadResource(client);
-
- // Print organization name
- System.out.println(org.getName().getValue());
-
- }
-
-}
-//END SNIPPET: client
-
diff --git a/hapi-fhir-base/src/site/example/java/example/MyPatientUse.java b/hapi-fhir-base/src/site/example/java/example/MyPatientUse.java
deleted file mode 100644
index eed0fd197be..00000000000
--- a/hapi-fhir-base/src/site/example/java/example/MyPatientUse.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package example;
-
-import java.io.IOException;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.model.primitive.DateTimeDt;
-import ca.uhn.fhir.model.primitive.StringDt;
-import ca.uhn.fhir.parser.DataFormatException;
-import ca.uhn.fhir.parser.IParser;
-import ca.uhn.fhir.parser.MyPatient;
-
-public class MyPatientUse {
-
-@SuppressWarnings("unused")
-public static void main(String[] args) throws DataFormatException, IOException {
-//START SNIPPET: patientUse
-MyPatient patient = new MyPatient();
-patient.setPetName(new StringDt("Fido"));
-patient.getImportantDates().add(new DateTimeDt("2010-01-02"));
-patient.getImportantDates().add(new DateTimeDt("2014-01-26T11:11:11"));
-
-patient.addName().addFamily("Smith").addGiven("John").addGiven("Quincy").addSuffix("Jr");
-
-IParser p = new FhirContext().newXmlParser().setPrettyPrint(true);
-String messageString = p.encodeResourceToString(patient);
-
-System.out.println(messageString);
-//END SNIPPET: patientUse
-
-//START SNIPPET: patientParse
-IParser parser = new FhirContext().newXmlParser();
-MyPatient newPatient = parser.parseResource(MyPatient.class, messageString);
-//END SNIPPET: patientParse
-
-{
- FhirContext ctx2 = new FhirContext();
- RuntimeResourceDefinition def = ctx2.getResourceDefinition(patient);
- System.out.println(ctx2.newXmlParser().setPrettyPrint(true).encodeResourceToString(def.toProfile()));
-}
-}
-
-}
diff --git a/hapi-fhir-base/src/site/site.xml b/hapi-fhir-base/src/site/site.xml
index 6bef354a5e2..6ce7a5bd2fd 100644
--- a/hapi-fhir-base/src/site/site.xml
+++ b/hapi-fhir-base/src/site/site.xml
@@ -61,6 +61,7 @@
+
diff --git a/hapi-fhir-base/src/site/xdoc/doc_extensions.xml b/hapi-fhir-base/src/site/xdoc/doc_extensions.xml
index 2f822f711ed..003c86bf4f7 100644
--- a/hapi-fhir-base/src/site/xdoc/doc_extensions.xml
+++ b/hapi-fhir-base/src/site/xdoc/doc_extensions.xml
@@ -28,7 +28,7 @@
-
+