Merge branch 'master' of github.com:jamesagnew/hapi-fhir

Conflicts:
	hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
This commit is contained in:
James Agnew 2014-08-20 15:24:39 -04:00
commit 1ec49a4f80
89 changed files with 2651 additions and 1122 deletions

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

1
hapi-fhir-base/examples/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target/

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>hapi-fhir-base-examples</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8

View File

@ -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

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
formatter_profile=_examples-format
formatter_settings_version=12

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-base-examples</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Examples (for site)</name>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>0.6-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit_version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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
}
}
}

View File

@ -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<Patient> 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<Patient> 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

View File

@ -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<IResource> response = client.transaction()
}
public static void main(String[] args) {
// nothing
simpleExample();
}
}

View File

@ -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<DateTimeDt> getImportantDates() {
if (myImportantDates==null) {
myImportantDates=new ArrayList<DateTimeDt>();
}
return myImportantDates;
}
public void setImportantDates(List<DateTimeDt> 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<DateTimeDt> 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()));
}
}
}

View File

@ -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<Patient> getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) DateParam theParam);
}
private boolean detectedVersionConflict;
private boolean conflictHappened;
private boolean couldntFindThisId;

View File

@ -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<Patient> getAllPatients() {
ArrayList<Patient> retVal = new ArrayList<Patient>();
// 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
}

View File

@ -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<Tag> 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<Patient> getAllPatients() {
ArrayList<Patient> retVal = new ArrayList<Patient>();
// 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
}

View File

@ -8,10 +8,10 @@
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<packaging>jar</packaging>
<url>http://hl7api.sourceforge.net/hapi-fhir/</url>
<url>http://jamesagnew.github.io/hapi-fhir/</url>
<name>HAPI FHIR - Core Library</name>
@ -20,14 +20,11 @@
<id>git.server</id>
<url>scm:git:git@github.com:jamesagnew/hapi-fhir.git</url>
</site>
<!-- <site> <id>hl7api.sf.net</id> <url>scp://shell.sourceforge.net/home/project-web/hl7api/htdocs/hapi-fhir</url> </site> -->
</distributionManagement>
<dependencies>
<!-- JSON -->
<!-- <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.2.4</version> </dependency> -->
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>

View File

@ -7,9 +7,11 @@
</properties>
<body>
<release version="0.6" date="TBD">
<!--
<action type="add">
Allow generic client ... OAUTH
</action>
-->
<action type="fix">
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!
</action>
<action type="add">
Server now adds a profile tag to returned results if the resource being returned
doesn't already have one
</action>
<action type="fix">
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!
</action>
<action type="fix">
Category header (for tags) is correctly read in client for "read" operation
</action>
<action type="add">
Transaction method in server can now have parameter type Bundle instead of
List&lt;IResource&gt;
</action>
<action type="add">
HAPI parsers now use field access to get/set values instead of method accessors and mutators.
This should give a small performance boost.
</action>
<action type="fix">
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!
</action>
</release>
<release version="0.5" date="2014-Jul-30">
<action type="add">

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -60,8 +60,8 @@ public class RuntimeResourceDefinition extends BaseRuntimeElementCompositeDefini
private List<RuntimeSearchParam> 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();
}

View File

@ -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<IdDt, IResource> myIdToEntries;
//@formatter:off
/* ****************************************************
* NB: add any new fields to the isEmpty() method!!!
*****************************************************/
//@formatter:on
private List<BundleEntry> 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.
* <p>
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
* <code>http://bar/Patient/123</code>. 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.
* <b>Important usage notes</b>: This method ignores base URLs (so passing in an ID of
* <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
* <code>http://bar/Patient/123</code>. 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.
* </p>
*
* @param theId The resource ID
* @param theId
* The resource ID
* @return Returns the resource with the given ID, or <code>null</code> 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 = "<Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://fhir.connectinggta.ca/Profile/organization#providerIdPool\">\n" +
// " <valueUri value=\"urn:oid:2.16.840.1.113883.3.239.23.21.1\"/>\n" +
// " </extension>\n" +
// " <text>\n" +
// " <status value=\"generated\"/>\n" +
// " <div xmlns=\"http://www.w3.org/1999/xhtml\"/>\n" +
// " </text>\n" +
// " <identifier>\n" +
// " <use value=\"official\"/>\n" +
// " <label value=\"HSP 2.16.840.1.113883.3.239.23.21\"/>\n" +
// " <system value=\"urn:cgta:hsp_ids\"/>\n" +
// " <value value=\"urn:oid:2.16.840.1.113883.3.239.23.21\"/>\n" +
// " </identifier>\n" +
// " <name value=\"火星第五人民医院\"/>\n" +
// "</Organization>";
//
// IGenericClient c = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/base");
// c.registerInterceptor(new LoggingInterceptor(true));
// c.update().resource(txt).withId("1665").execute();
// }
//
// public static void main(String[] args) {
//
// FhirContext ctx = new FhirContext();
// String txt = "<Organization xmlns=\"http://hl7.org/fhir\">\n" +
// " <extension url=\"http://fhir.connectinggta.ca/Profile/organization#providerIdPool\">\n" +
// " <valueUri value=\"urn:oid:2.16.840.1.113883.3.239.23.21.1\"/>\n" +
// " </extension>\n" +
// " <text>\n" +
// " <status value=\"generated\"/>\n" +
// " <div xmlns=\"http://www.w3.org/1999/xhtml\"/>\n" +
// " </text>\n" +
// " <identifier>\n" +
// " <use value=\"official\"/>\n" +
// " <label value=\"HSP 2.16.840.1.113883.3.239.23.21\"/>\n" +
// " <system value=\"urn:cgta:hsp_ids\"/>\n" +
// " <value value=\"urn:oid:2.16.840.1.113883.3.239.23.21\"/>\n" +
// " </identifier>\n" +
// " <name value=\"火星第五人民医院\"/>\n" +
// "</Organization>";
//
// 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<BundleEntry> getEntries() {
if (myEntries == null) {
myEntries = new ArrayList<BundleEntry>();
@ -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);
@ -312,6 +332,24 @@ 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<IResource> theUploadBundle, FhirContext theContext, String theServerBase) {
public static Bundle withResources(List<IResource> theResources, FhirContext theContext, String theServerBase) {
Bundle retVal = new Bundle();
for (IResource next : theUploadBundle) {
for (IResource next : theResources) {
retVal.addResource(next, theContext, theServerBase);
}
return retVal;

View File

@ -197,6 +197,52 @@ public abstract class ResourceMetadataKeyEnum<T> {
}
};
/**
* If present and populated with a string, provides the "search link" (the link
* element in the bundle entry with <code>rel="search"</code>). 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.
* <p>
* Values for this key are of type <b>{@link String}</b>
* </p>
*/
public static final ResourceMetadataKeyEnum<String> LINK_SEARCH = new ResourceMetadataKeyEnum<String>("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 <code>rel="alternate"</code>). 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.
* <p>
* Values for this key are of type <b>{@link String}</b>
* </p>
*/
public static final ResourceMetadataKeyEnum<String> LINK_ALTERNATE = new ResourceMetadataKeyEnum<String>("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) {

View File

@ -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";

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.model.api;
*/
import java.util.ArrayList;
import java.util.List;
public class TagList extends ArrayList<Tag> {
@ -48,7 +49,7 @@ public class TagList extends ArrayList<Tag> {
return null;
}
public ArrayList<Tag> getTagsWithScheme(String theScheme) {
public List<Tag> getTagsWithScheme(String theScheme) {
ArrayList<Tag> retVal = new ArrayList<Tag>();
for (Tag next : this) {
if (theScheme.equals(next.getScheme())) {

View File

@ -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

View File

@ -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<String> {
return isNotBlank(getVersionIdPart());
}
/**
* Returns <code>true</code> 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 <code>true</code> if the unqualified ID is a valid {@link Long} value (in other words, it consists only
* of digits)

View File

@ -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;

View File

@ -167,6 +167,8 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.writeEnd();
}
writeCategories(eventWriter, theBundle.getCategories());
writeOptionalTagWithTextNode(eventWriter, "totalResults", theBundle.getTotalResults());
writeAuthor(theBundle, eventWriter);
@ -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;

View File

@ -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<T> {
@ -474,6 +474,12 @@ class ParserState<T> {
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<T> {
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<T> {
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,19 +1257,31 @@ class ParserState<T> {
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);
}
}
}
}
}
}
});
}

View File

@ -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();
}

View File

@ -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 <code>{@link Bundle}</code> or of type
* <code>{@link List}&lt;IResource&gt;</code>
*/
@Target(value=ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionParam {

View File

@ -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<MethodOutcome> {
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<Metho
TagList tagList = new TagList();
for (Enumeration<String> 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<Metho
// getMethod().in
}
static void parseTagValue(TagList tagList, String nextTagComplete) {
StringBuilder next = new StringBuilder(nextTagComplete);
parseTagValue(tagList, nextTagComplete, next);
public boolean isReturnVoid() {
return myReturnVoid;
}
/**
* @throws IOException
*/
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServer.determineRequestEncoding(theRequest);
IParser parser = encoding.newParser(getContext());
IResource resource = parser.parseResource(theRequest.getServletRequest().getReader());
return resource;
private void addLocationHeader(Request theRequest, HttpServletResponse theResponse, MethodOutcome response) {
StringBuilder b = new StringBuilder();
b.append(theRequest.getFhirServerBase());
b.append('/');
b.append(getResourceName());
b.append('/');
b.append(response.getId().getIdPart());
if (response.getId().hasVersionIdPart()) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getId().getVersionIdPart());
} else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getVersionId().getValue());
}
theResponse.addHeader(Constants.HEADER_LOCATION, b.toString());
}
/*
@ -257,99 +258,6 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
* encoding.newParser(getContext()); parser.encodeResourceToWriter(outcome, writer); } } finally { writer.close(); } // getMethod().in }
*/
public boolean isReturnVoid() {
return myReturnVoid;
}
private void addLocationHeader(Request theRequest, HttpServletResponse theResponse, MethodOutcome response) {
StringBuilder b = new StringBuilder();
b.append(theRequest.getFhirServerBase());
b.append('/');
b.append(getResourceName());
b.append('/');
b.append(response.getId().getIdPart());
if (response.getId().hasVersionIdPart()) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getId().getVersionIdPart());
} else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getVersionId().getValue());
}
theResponse.addHeader(Constants.HEADER_LOCATION, b.toString());
}
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);
}
}
protected abstract void addParametersForServerRequest(Request theRequest, Object[] theParams);
/**
@ -366,6 +274,16 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
*/
protected abstract String getMatchingOperation();
/**
* @throws IOException
*/
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServer.determineRequestEncoding(theRequest);
IParser parser = encoding.newParser(getContext());
IResource resource = parser.parseResource(theRequest.getServletRequest().getReader());
return resource;
}
protected abstract Set<RequestType> provideAllowableRequestTypes();
/**
@ -425,4 +343,5 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
}
}
}

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.method;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.io.PushbackReader;
@ -79,6 +79,8 @@ import ca.uhn.fhir.util.ReflectionUtil;
*/
public class MethodUtil {
private static final String LABEL = "label=\"";
private static final String SCHEME = "scheme=\"";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
@ -132,8 +134,95 @@ public class MethodUtil {
String headerValue = clHeaders.get(0);
resource.getId().setValue(headerValue);
}
List<String> 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) {

View File

@ -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;
@ -54,7 +54,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
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<IResource> resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
List<IdDt> oldIds= new ArrayList<IdDt>();
for (IResource next : resources) {
oldIds.add(next.getId());
// Grab the IDs of all of the resources in the transaction
List<IResource> resources;
if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
} else {
resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
}
Object response= invokeServerMethod(theMethodParams);
IdentityHashMap<IResource, IdDt> oldIds = new IdentityHashMap<IResource, IdDt>();
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,13 +120,16 @@ 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<IResource> retResources = retVal.getResources(offset, retVal.size());
for (int i =0; i < resources.size(); i++) {
IdDt oldId = oldIds.get(i);
List<IResource> 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()) {
@ -130,7 +140,10 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
}
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<IResource> resources = (List<IResource>) 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<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex];
return createTransactionInvocation(resources, context);
}
}
public static BaseHttpClientInvocation createTransactionInvocation(List<IResource> theResources, FhirContext theContext) {

View File

@ -38,6 +38,8 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class TransactionParamBinder implements IParameter {
private boolean myParamIsBundle;
public TransactionParamBinder() {
}
@ -50,6 +52,9 @@ class TransactionParamBinder implements IParameter {
@Override
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
Bundle resource = (Bundle) theRequestContents;
if (myParamIsBundle) {
return resource;
}
ArrayList<IResource> retVal = new ArrayList<IResource>();
for (BundleEntry next : resource.getEntries()) {
@ -64,13 +69,24 @@ class TransactionParamBinder implements IParameter {
@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");
}
}
}

View File

@ -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;

View File

@ -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<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();

View File

@ -856,8 +856,8 @@ public class RestfulServer extends HttpServlet {
} while (references.isEmpty() == false);
BundleEntry entry = bundle.addResource(next, theContext, theServerBase);
addProfileToBundleEntry(theContext, next, entry);
bundle.addResource(next, theContext, theServerBase);
// addProfileToBundleEntry(theContext, next, entry);
}
@ -865,24 +865,26 @@ public class RestfulServer extends HttpServlet {
* 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<Tag> profileTags = entry.getCategories().getTagsWithScheme(Constants.TAG_SCHEME_PROFILE);
List<Tag> 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();

View File

@ -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);
}

View File

@ -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 <code>null</code>
* 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 <code>null</code>
*/
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 <code>null</code>
* 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 <code>null</code> otherwise.
* <p>
* In a restful server, this method is currently ignored.
* </p>
@ -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.
* <p>
* In a restful server, this method is currently ignored.
* </p>
@ -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;

View File

@ -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,30 +109,68 @@ public class FhirTerser {
}
/**
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b>
* 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 <b>non-empty</b> and are
* either of the exact type specified, or are a subclass of that type.
* <p>
* 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.
* 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.
* </p>
* @param theResourceT The resource instance to search. Must not be null.
* @param theType The type to search for. Must not be null.
*
* @param theResourceT
* The resource instance to search. Must not be null.
* @param theType
* The type to search for. Must not be null.
* @return
*/
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, Class<T> theType) {
ArrayList<T> retVal = new ArrayList<T>();
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, final Class<T> theType) {
final ArrayList<T> retVal = new ArrayList<T>();
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 <T extends IElement> void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition<?> theDefinition, Class<T> theType, ArrayList<T> theList) {
if (theElement.isEmpty()) {
return;
}
private <T extends IElement> void visit(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
theCallback.acceptElement(theElement, theChildDefinition, theDefinition);
addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
addIfCorrectType(theElement, theType, theList);
addUndeclaredExtensions(theElement, theType, theList);
// if (theElement.isEmpty()) {
// return;
// }
switch (theDefinition.getChildType()) {
case PRIMITIVE_XHTML:
@ -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 <T extends IElement> void addUndeclaredExtensions(IElement theElement, Class<T> theType, ArrayList<T> theList) {
private <T extends IElement> 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 <T extends IElement> void addIfCorrectType(IElement theElement, Class<T> theType, ArrayList<T> theList) {
if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
theList.add((T) theElement);
}
}
}

View File

@ -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);
}

View File

@ -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://");
}
}

View File

@ -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
}
}
}

View File

@ -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<Patient> 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<Patient> 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

View File

@ -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()));
}
}
}

View File

@ -61,6 +61,7 @@
<item name="The Data Model" href="./doc_fhirobjects.html">
<item name="Extensions" href="./doc_extensions.html" />
<item name="Resource References" href="./doc_resource_references.html" />
<item name="Tags" href="./doc_tags.html" />
</item>
<item name="RESTful Client" href="./doc_rest_client.html" />
<item name="RESTful Server" href="./doc_rest_server.html" >

View File

@ -28,7 +28,7 @@
</p>
<macro name="snippet">
<param name="id" value="resourceExtension" />
<param name="file" value="src/site/example/java/example/Extensions.java" />
<param name="file" value="examples/src/main/java/example/Extensions.java" />
</macro>
<p>
@ -36,7 +36,7 @@
</p>
<macro name="snippet">
<param name="id" value="resourceStringExtension" />
<param name="file" value="src/site/example/java/example/Extensions.java" />
<param name="file" value="examples/src/main/java/example/Extensions.java" />
</macro>
<subsection name="Sub-Extensions">
@ -48,7 +48,7 @@
</p>
<macro name="snippet">
<param name="id" value="subExtension" />
<param name="file" value="src/site/example/java/example/Extensions.java" />
<param name="file" value="examples/src/main/java/example/Extensions.java" />
</macro>
</subsection>
@ -61,7 +61,7 @@
</p>
<macro name="snippet">
<param name="id" value="parseExtension" />
<param name="file" value="src/site/example/java/example/Extensions.java" />
<param name="file" value="examples/src/main/java/example/Extensions.java" />
</macro>
</subsection>
@ -78,7 +78,7 @@
<macro name="snippet">
<param name="id" value="patientDef" />
<param name="file" value="src/site/example/java/example/MyPatient.java" />
<param name="file" value="examples/src/main/java/example/MyPatient.java" />
</macro>
<p>
@ -88,7 +88,7 @@
<macro name="snippet">
<param name="id" value="patientUse" />
<param name="file" value="src/site/example/java/example/MyPatientUse.java" />
<param name="file" value="examples/src/main/java/example/MyPatientUse.java" />
</macro>
<p>
@ -121,7 +121,7 @@
<macro name="snippet">
<param name="id" value="patientParse" />
<param name="file" value="src/site/example/java/example/MyPatientUse.java" />
<param name="file" value="examples/src/main/java/example/MyPatientUse.java" />
</macro>
<subsection name="Documentation">

View File

@ -31,7 +31,7 @@
<macro name="snippet">
<param name="id" value="datatypes" />
<param name="file" value="src/site/example/java/example/FhirDataModel.java" />
<param name="file" value="examples/src/main/java/example/FhirDataModel.java" />
</macro>
<subsection name="Navigating Structures">
@ -45,7 +45,7 @@
<macro name="snippet">
<param name="id" value="nonNull" />
<param name="file" value="src/site/example/java/example/FhirDataModel.java" />
<param name="file" value="examples/src/main/java/example/FhirDataModel.java" />
</macro>
</subsection>
@ -65,7 +65,7 @@
<macro name="snippet">
<param name="id" value="codes" />
<param name="file" value="src/site/example/java/example/FhirDataModel.java" />
<param name="file" value="examples/src/main/java/example/FhirDataModel.java" />
</macro>
</subsection>
@ -87,7 +87,7 @@
<macro name="snippet">
<param name="id" value="namesHard" />
<param name="file" value="src/site/example/java/example/FhirDataModel.java" />
<param name="file" value="examples/src/main/java/example/FhirDataModel.java" />
</macro>
<p>
@ -97,7 +97,7 @@
<macro name="snippet">
<param name="id" value="namesEasy" />
<param name="file" value="src/site/example/java/example/FhirDataModel.java" />
<param name="file" value="examples/src/main/java/example/FhirDataModel.java" />
</macro>
</subsection>

View File

@ -70,7 +70,7 @@
<macro name="snippet">
<param name="id" value="creatingContext" />
<param name="file" value="src/site/example/java/example/FhirContextIntro.java" />
<param name="file" value="examples/src/main/java/example/FhirContextIntro.java" />
</macro>
</subsection>
@ -93,7 +93,7 @@
<macro name="snippet">
<param name="id" value="parseMsg" />
<param name="file" value="src/site/example/java/example/FhirContextIntro.java" />
<param name="file" value="examples/src/main/java/example/FhirContextIntro.java" />
</macro>
</subsection>
@ -107,7 +107,7 @@
<macro name="snippet">
<param name="id" value="encodeMsg" />
<param name="file" value="src/site/example/java/example/FhirContextIntro.java" />
<param name="file" value="examples/src/main/java/example/FhirContextIntro.java" />
</macro>
<!-- ****** The section below on fluent references the snippet above
@ -147,7 +147,7 @@
<macro name="snippet">
<param name="id" value="encodeMsgFluent" />
<param name="file" value="src/site/example/java/example/FhirContextIntro.java" />
<param name="file" value="examples/src/main/java/example/FhirContextIntro.java" />
</macro>
</subsection>
@ -160,7 +160,7 @@
<macro name="snippet">
<param name="id" value="encodeMsgJson" />
<param name="file" value="src/site/example/java/example/FhirContextIntro.java" />
<param name="file" value="examples/src/main/java/example/FhirContextIntro.java" />
</macro>
<p>

View File

@ -28,7 +28,7 @@
<macro name="snippet">
<param name="id" value="simple" />
<param name="file" value="src/site/example/java/example/Narrative.java" />
<param name="file" value="examples/src/main/java/example/Narrative.java" />
</macro>
</section>
@ -64,7 +64,7 @@
<macro name="snippet">
<param name="id" value="example1" />
<param name="file" value="src/site/example/java/example/Narrative.java" />
<param name="file" value="examples/src/main/java/example/Narrative.java" />
</macro>
<p>
@ -163,7 +163,7 @@ humanname.narrative=classpath:ca/uhn/fhir/narrative/HumanNameDt.html]]></source>
<macro name="snippet">
<param name="id" value="gen" />
<param name="file" value="src/site/example/java/example/NarrativeGenerator.java" />
<param name="file" value="examples/src/main/java/example/NarrativeGenerator.java" />
</macro>
</section>

View File

@ -27,8 +27,9 @@
There are two types of clients provided by HAPI: Generic and Annotation-driven.
The generic client (introduced in HAPI-FHIR 0.3) is much simpler to create
and generally provides the faster way to get started. The annotation-driven
client is more powerful and can rely on code generation to give better
compile-time checking.
client can rely on code generation and static binding to specific operations to
give better compile-time checking against servers with a specific set of capabilities
exposed.
</p>
</section>
@ -47,7 +48,7 @@
<macro name="snippet">
<param name="id" value="simple" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<p>
@ -76,27 +77,19 @@
</p>
</subsection>
<subsection name="Type - Create">
<p>
The following example shows how to perform a create
operation using the generic client:
</p>
<macro name="snippet">
<param name="id" value="create" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Type - Search/Query">
<p>
Searching for resources is probably the most common initial scenario for
client applications, so we'll start the demonstration there.
</p>
<p>
The following example shows how to query using the generic client:
</p>
<macro name="snippet">
<param name="id" value="search" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Multi-valued Parameters (ANY/OR)</h4>
@ -108,7 +101,7 @@
<macro name="snippet">
<param name="id" value="searchOr" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Multi-valued Parameters (ALL/AND)</h4>
@ -120,7 +113,7 @@
<macro name="snippet">
<param name="id" value="searchOr" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Paging</h4>
@ -131,7 +124,7 @@
<macro name="snippet">
<param name="id" value="searchPaging" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Composite Parameters</h4>
@ -144,7 +137,7 @@
<macro name="snippet">
<param name="id" value="searchComposite" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Other Query Options</h4>
@ -155,7 +148,7 @@
<macro name="snippet">
<param name="id" value="searchAdv" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<h4>Search - Using HTTP POST or GET with _search</h4>
@ -168,11 +161,23 @@
<macro name="snippet">
<param name="id" value="searchPost" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Type - Create">
<p>
The following example shows how to perform a create
operation using the generic client:
</p>
<macro name="snippet">
<param name="id" value="create" />
<param name="file"
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Instance - Delete">
<p>
The following example shows how to perform a delete
@ -181,7 +186,7 @@
<macro name="snippet">
<param name="id" value="delete" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
@ -198,7 +203,7 @@
<macro name="snippet">
<param name="id" value="update" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
@ -210,7 +215,7 @@
<macro name="snippet">
<param name="id" value="conformance" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
@ -221,7 +226,7 @@
<macro name="snippet">
<param name="id" value="transaction" />
<param name="file"
value="src/site/example/java/example/GenericClientExample.java" />
value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
@ -295,7 +300,7 @@
<macro name="snippet">
<param name="id" value="provider" />
<param name="file"
value="src/site/example/java/example/IRestfulClient.java" />
value="examples/src/main/java/example/IRestfulClient.java" />
</macro>
<p>
@ -321,7 +326,7 @@
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="src/site/example/java/example/ExampleRestfulClient.java" />
value="examples/src/main/java/example/ExampleRestfulClient.java" />
</macro>
</subsection>
@ -343,7 +348,7 @@
<macro name="snippet">
<param name="id" value="clientConfig" />
<param name="file" value="src/site/example/java/example/ClientExamples.java" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>
@ -359,7 +364,7 @@
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="src/site/example/java/example/CompleteExampleClient.java" />
value="examples/src/main/java/example/CompleteExampleClient.java" />
</macro>
</subsection>
@ -412,7 +417,7 @@
<macro name="snippet">
<param name="id" value="security" />
<param name="file" value="src/site/example/java/example/ClientExamples.java" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>
@ -429,7 +434,7 @@
<macro name="snippet">
<param name="id" value="logging" />
<param name="file" value="src/site/example/java/example/ClientExamples.java" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>
@ -443,7 +448,7 @@
<macro name="snippet">
<param name="id" value="logging" />
<param name="file" value="src/site/example/java/example/ClientExamples.java" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>

View File

@ -202,7 +202,7 @@
<macro name="snippet">
<param name="id" value="read" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -218,7 +218,7 @@
<macro name="snippet">
<param name="id" value="clientReadInterface" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<a name="instance_vread" />
@ -243,7 +243,7 @@
<macro name="snippet">
<param name="id" value="vread" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -294,7 +294,7 @@
<macro name="snippet">
<param name="id" value="update" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -311,7 +311,7 @@
<macro name="snippet">
<param name="id" value="updateClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<a name="instance_delete" />
@ -336,7 +336,7 @@
<macro name="snippet">
<param name="id" value="delete" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -407,7 +407,7 @@
<macro name="snippet">
<param name="id" value="create" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -424,7 +424,7 @@
<macro name="snippet">
<param name="id" value="createClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<a name="type_search" />
@ -456,7 +456,7 @@
<macro name="snippet">
<param name="id" value="searchAll" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -495,7 +495,7 @@
<macro name="snippet">
<param name="id" value="searchStringParam" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -517,7 +517,7 @@
<macro name="snippet">
<param name="id" value="searchIdentifierParam" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -550,7 +550,7 @@
<macro name="snippet">
<param name="id" value="dates" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -565,7 +565,7 @@
<macro name="snippet">
<param name="id" value="dateClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -597,7 +597,7 @@
</p>
<macro name="snippet">
<param name="id" value="dateRange" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -612,7 +612,7 @@
<macro name="snippet">
<param name="id" value="dateClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<h4>Unbounded Ranges</h4>
@ -658,7 +658,7 @@
</p>
<macro name="snippet">
<param name="id" value="quantity" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -699,7 +699,7 @@
<macro name="snippet">
<param name="id" value="reference" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -722,7 +722,7 @@
<macro name="snippet">
<param name="id" value="referenceChain" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -744,7 +744,7 @@
<macro name="snippet">
<param name="id" value="searchComposite" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -800,7 +800,7 @@
<macro name="snippet">
<param name="id" value="searchOptionalParam" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -878,7 +878,7 @@
<macro name="snippet">
<param name="id" value="searchMultiple" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -910,7 +910,7 @@
<macro name="snippet">
<param name="id" value="searchMultipleAnd" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<h4>AND Relationship Query Parameters for Dates</h4>
@ -940,7 +940,7 @@
<macro name="snippet">
<param name="id" value="pathSpec" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -957,7 +957,7 @@
<macro name="snippet">
<param name="id" value="pathSpecSimple" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -979,7 +979,7 @@
<macro name="snippet">
<param name="id" value="searchNamedQuery" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1016,7 +1016,7 @@
<macro name="snippet">
<param name="id" value="sort" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1041,7 +1041,7 @@
<macro name="snippet">
<param name="id" value="searchWithDocs" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -1108,7 +1108,7 @@
<macro name="snippet">
<param name="id" value="validate" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1150,7 +1150,7 @@
</p>
<macro name="snippet">
<param name="id" value="metadataProvider" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1160,7 +1160,7 @@
</p>
<macro name="snippet">
<param name="id" value="metadataClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1171,7 +1171,7 @@
</p>
<macro name="snippet">
<param name="id" value="metadataClientUsage" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<a name="system_transaction" />
@ -1198,9 +1198,14 @@
</p>
<macro name="snippet">
<param name="id" value="transaction" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
Transaction methods require one parameter annotated with @TransactionParam, and that
parameter may be of type List&lt;IResource&gt; or Bundle.
</p>
<p>
Example URL to invoke this method:
<br />
@ -1315,7 +1320,7 @@
<macro name="snippet">
<param name="id" value="history" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1324,7 +1329,7 @@
<macro name="snippet">
<param name="id" value="historyClient" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<a name="exceptions" />
@ -1406,7 +1411,7 @@
<macro name="snippet">
<param name="id" value="readTags" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>
@ -1417,7 +1422,7 @@
<macro name="snippet">
<param name="id" value="clientReadTags" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -1444,7 +1449,7 @@
<macro name="snippet">
<param name="id" value="createTags" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
</subsection>
@ -1464,7 +1469,7 @@
</p>
<macro name="snippet">
<param name="id" value="tagMethodProvider" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
<p>

View File

@ -57,7 +57,7 @@
<macro name="snippet">
<param name="id" value="provider" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProvider.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProvider.java" />
</macro>
</subsection>
@ -88,7 +88,7 @@
<macro name="snippet">
<param name="id" value="servlet" />
<param name="file" value="src/site/example/java/example/ExampleRestfulServlet.java" />
<param name="file" value="examples/src/main/java/example/ExampleRestfulServlet.java" />
</macro>
<a name="plain_providers"/>
@ -120,7 +120,7 @@
</p>
<macro name="snippet">
<param name="id" value="plainProvider" />
<param name="file" value="src/site/example/java/example/ExampleProviders.java" />
<param name="file" value="examples/src/main/java/example/ExampleProviders.java" />
</macro>
<p>
@ -136,7 +136,7 @@
</p>
<macro name="snippet">
<param name="id" value="plainProviderServer" />
<param name="file" value="src/site/example/java/example/ExampleProviders.java" />
<param name="file" value="examples/src/main/java/example/ExampleProviders.java" />
</macro>
</subsection>
@ -258,7 +258,7 @@
<macro name="snippet">
<param name="id" value="provider" />
<param name="file" value="src/site/example/java/example/PagingServer.java" />
<param name="file" value="examples/src/main/java/example/PagingServer.java" />
</macro>
</subsection>
@ -290,7 +290,7 @@
<macro name="snippet">
<param name="id" value="provider" />
<param name="file" value="src/site/example/java/example/PagingPatientProvider.java" />
<param name="file" value="examples/src/main/java/example/PagingPatientProvider.java" />
</macro>
</subsection>
@ -323,7 +323,7 @@
<macro name="snippet">
<param name="id" value="underlyingReq" />
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
</macro>
@ -435,6 +435,41 @@
</section>
<section name="Populating Resource Metadata">
<p>
Server operations will often return a resource or a bundle of resources. These
types will contain one or more resource instances, but also specify a set of
metadata describing that resource.
</p>
<p>
For example, resources have a "published" and "updated" date, referring to
the date/time the resource was originally created and the date/time the
resource was last updated respectively. For operations which return a single
resource, these values are returned via HTTP headers. For operations which
return a bundle, these values are returned via elements within the
bundle's "entry" tag.
</p>
<p>
Bundles may also contain a set of links, such as an "alternate" link to
a resource, or a "search" link.
</p>
<p>
Populating these metadata elements is done via the
<code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/api/IResource.html#getResourceMetadata()">IResource#getResourceMetadata()</a></code>
method. The following example shows how to set various metadata elements on
a resource being returned.
</p>
<macro name="snippet">
<param name="id" value="serverMethod" />
<param name="file" value="examples/src/main/java/example/ServerMetadataExamples.java" />
</macro>
</section>
<section name="A Complete Example">
<p>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Resource Tags - HAPI FHIR</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Working With Tags">
<p>
FHIR defines a useful framework for adding/updating/removing
<a href="http://www.hl7.org/implement/standards/fhir/extras.html#tag">Tags</a>
against resource instances. A tag is a pair of URLs (a scheme, and a term) which
can optionally have a textual "label" as well.
</p>
<p>
A specific resource instance's tags can be found in the resource
<a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/api/IResource.html#getResourceMetadata()">metadata</a>
map, using the key of
<a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/api/ResourceMetadataKeyEnum.html#TAG_LIST">ResourceMetadataKeyEnum.TAG_LIST</a>.
The following example shows how to access the tags in a client
following a "read" operation:
</p>
<macro name="snippet">
<param name="id" value="getResourceTags" />
<param name="file" value="examples/src/main/java/example/TagsExamples.java" />
</macro>
<subsection name="Adding Tags to a Resource">
<p>
In a server implementation, you might want to
add tags to a resource being returned. This is done
by adding a TagList instance to the resource's
metadata, as shown in the example below.
</p>
<p>
The server will then do the "right thing" with the tags. If the method
is for a <code>search</code> operation, the tags will be added to the category
element in the
returned bundle. If the method is for a <code>read</code> operation, the
tags will be added to the response "Category" headers.
</p>
<macro name="snippet">
<param name="id" value="serverMethod" />
<param name="file" value="examples/src/main/java/example/TagsExamples.java" />
</macro>
</subsection>
</section>
</body>
</document>

View File

@ -30,6 +30,9 @@ public class ModelExtensionTest {
MyPatient parsed = ourCtx.newXmlParser().parseResource(MyPatient.class, str);
assertEquals("foo", parsed.getIdentifierFirstRep().getSystem().getValueAsString());
// assertEquals(MyOrganization.class, parsed.getManagingOrganization().getResource().getClass());
// MyOrganization parsedOrg = (MyOrganization) parsed.getManagingOrganization().getResource();
// assertEquals("arg0", parsedOrg.getName().getValue());
}
}

View File

@ -5,7 +5,9 @@ import static org.junit.Assert.*;
import org.junit.Test;
import ca.uhn.fhir.model.dstu.resource.CarePlan;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.MyPatient;
public class ModelScannerTest {
@ -15,6 +17,16 @@ public class ModelScannerTest {
new ModelScanner(CarePlan.class);
}
@Test
public void testExtendedClass() {
FhirContext ctx = new FhirContext();
ctx.getResourceDefinition(MyPatient.class);
ctx.getResourceDefinition(Patient.class);
RuntimeResourceDefinition patient = ctx.getResourceDefinition("Patient");
assertEquals(Patient.class, patient.getImplementingClass());
}
@Test
public void testScanExtensionTypes() throws DataFormatException {

View File

@ -363,6 +363,29 @@ public class JsonParserTest {
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
b.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = new FhirContext().newJsonParser().setPrettyPrint(false).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("\"category\":[{\"term\":\"term\",\"label\":\"label\",\"scheme\":\"scheme\"}]"));
b = new FhirContext().newJsonParser().parseBundle(val);
assertEquals(1,b.getEntries().size());
assertEquals(1,b.getCategories().size());
assertEquals("term", b.getCategories().get(0).getTerm());
assertEquals("label", b.getCategories().get(0).getLabel());
assertEquals("scheme", b.getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundleEntryCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
@ -383,7 +406,6 @@ public class JsonParserTest {
}
@Test
public void testEncodeContainedResources() throws IOException {
@ -542,7 +564,7 @@ public class JsonParserTest {
patient.setManagingOrganization(new ResourceReferenceDt("Organization/123"));
str = p.encodeResourceToString(patient);
assertThat(str, StringContains.containsString("\"managingOrganization\":{\"resource\":\"Organization/123\"}"));
assertThat(str, StringContains.containsString("\"managingOrganization\":{\"reference\":\"Organization/123\"}"));
Organization org = new Organization();
org.addIdentifier().setSystem("foo").setValue("bar");
@ -671,6 +693,11 @@ public class JsonParserTest {
IParser p = ourCtx.newJsonParser();
Bundle bundle = p.parseBundle(msg);
assertEquals(1, bundle.getCategories().size());
assertEquals("http://scheme", bundle.getCategories().get(0).getScheme());
assertEquals("http://term", bundle.getCategories().get(0).getTerm());
assertEquals("label", bundle.getCategories().get(0).getLabel());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
ourLog.info(encoded);

View File

@ -3,7 +3,7 @@ package ca.uhn.fhir.parser;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.dstu.resource.Organization;
@ResourceDef(name="Organization")
@ResourceDef()
public class MyOrganization extends Organization {
}

View File

@ -12,7 +12,7 @@ import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ResourceDef(name="Patient")
@ResourceDef()
public class MyPatient extends Patient {
@Child(name="petName")

View File

@ -63,16 +63,19 @@ import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
public class XmlParserTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
@Test
public void testParseLanguage() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\"><language value=\"zh-CN\"/><text><status value=\"generated\"/><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> 海生 <b>王 </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>URNo</td></tr><tr><td>Address</td><td><span>99 Houston Road </span><br/><span>BENTLEIGH </span><span>Victoria </span></td></tr><tr><td>Date of birth</td><td><span>01 January 1997</span></td></tr></tbody></table></div></text><identifier><use value=\"usual\"/><label value=\"URNo\"/><value value=\"89532\"/></identifier><name><text value=\"王海生\"/><family value=\"\"/><given value=\"海生\"/></name><telecom><system value=\"phone\"/><value value=\"9899 9878\"/><use value=\"home\"/></telecom><telecom><system value=\"email\"/><value value=\"zimmerman@datacorp.com.au\"/><use value=\"home\"/></telecom><gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\"/><code value=\"M\"/><display value=\"Male\"/></coding><text value=\"Male\"/></gender><birthDate value=\"1997-01-01\"/><address><use value=\"home\"/><text value=\"99 Houston Road, BENTLEIGH, 3204\"/><line value=\"99 Houston Road\"/><city value=\"BENTLEIGH\"/><state value=\"Victoria\"/><zip value=\"3204\"/><period><start value=\"2006-06-16\"/></period></address><active value=\"true\"/></Patient>";
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
public void testEncodeBinaryResource() {
Binary patient = new Binary();
patient.setContentType("foo");
patient.setContent(new byte[] {1,2,3,4});
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
assertEquals("zh-CN", pt.getLanguage().getValue());
}
@Test
@ -88,283 +91,10 @@ public class XmlParserTest {
}
@Test
public void testNestedContainedResources() {
Observation A = new Observation();
A.getName().setText("A");
Observation B = new Observation();
B.getName().setText("B");
A.addRelated().setTarget(new ResourceReferenceDt(B));
Observation C = new Observation();
C.getName().setText("C");
B.addRelated().setTarget(new ResourceReferenceDt(C));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A);
ourLog.info(str);
assertThat(str, stringContainsInOrder(Arrays.asList("<text value=\"B\"/>", "<text value=\"C\"/>", "<text value=\"A\"/>")));
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>")));
// Only one (outer) contained block
int idx0 = str.indexOf("<contained>");
int idx1 = str.indexOf("<contained>",idx0+1);
assertNotEquals(-1, idx0);
assertEquals(-1, idx1);
Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
assertEquals("A",obs.getName().getText().getValue());
Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource();
assertEquals("B",obsB.getName().getText().getValue());
Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource();
assertEquals("C",obsC.getName().getText().getValue());
}
@Test
public void testParseQuery() {
String msg = "<Query xmlns=\"http://hl7.org/fhir\">\n" +
" <text>\n" +
" <status value=\"generated\"/>\n" +
" <div xmlns=\"http://www.w3.org/1999/xhtml\">[Put rendering here]</div>\n" +
" </text>\n" +
"\n" +
" <!-- this is an extermely simple query - a request to execute the query 'example' on the\n" +
" responder -->\n" +
" <identifier value=\"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\"/>\n" +
" <parameter url=\"http://hl7.org/fhir/query#_query\">\n" +
" <valueString value=\"example\"/>\n" +
" </parameter>\n" +
"</Query>";
Query query = ourCtx.newXmlParser().parseResource(Query.class, msg);
assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString());
assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString());
assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString());
}
@Test
public void testEncodeQuery() {
Query q = new Query();
ExtensionDt parameter = q.addParameter();
parameter.setUrl("http://foo").setValue(new StringDt("bar"));
String val = ourCtx.newXmlParser().encodeResourceToString(q);
ourLog.info(val);
assertEquals("<Query xmlns=\"http://hl7.org/fhir\"><parameter url=\"http://foo\"><valueString value=\"bar\"/></parameter></Query>", val);
}
@Test
public void testEncodeBinaryResource() {
Binary patient = new Binary();
patient.setContentType("foo");
patient.setContent(new byte[] {1,2,3,4});
String val = ourCtx.newXmlParser().encodeResourceToString(patient);
assertEquals("<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>", val);
}
@Test
public void testParseBinaryResource() {
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
assertEquals("foo", val.getContentType());
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
}
@Test
public void testTagList() {
//@formatter:off
String tagListStr = "<taglist xmlns=\"http://hl7.org/fhir\"> \n" +
" <category term=\"term0\" label=\"label0\" scheme=\"scheme0\" /> \n" +
" <category term=\"term1\" label=\"label1\" scheme=\"\" /> \n" +
" <category term=\"term2\" label=\"label2\" /> \n" +
"</taglist>";
//@formatter:on
TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr);
assertEquals(3, tagList.size());
assertEquals("term0", tagList.get(0).getTerm());
assertEquals("label0", tagList.get(0).getLabel());
assertEquals("scheme0", tagList.get(0).getScheme());
assertEquals("term1", tagList.get(1).getTerm());
assertEquals("label1", tagList.get(1).getLabel());
assertEquals(null, tagList.get(1).getScheme());
assertEquals("term2", tagList.get(2).getTerm());
assertEquals("label2", tagList.get(2).getLabel());
assertEquals(null, tagList.get(2).getScheme());
/*
* Encode
*/
//@formatter:off
String expected = "<taglist xmlns=\"http://hl7.org/fhir\">" +
"<category term=\"term0\" label=\"label0\" scheme=\"scheme0\"/>" +
"<category term=\"term1\" label=\"label1\"/>" +
"<category term=\"term2\" label=\"label2\"/>" +
"</taglist>";
//@formatter:on
String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList);
assertEquals(expected,encoded);
}
@Test
public void testTotalResultsUsingOldNamespace() {
//@formatter:off
String bundle = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title>Search results for Patient</title>\n" +
" <id>urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8</id>\n" +
" <totalResults xmlns=\"http://purl.org/atompub/tombstones/1.0\">15</totalResults>\n" +
" <updated>2014-05-04T13:19:47.027-04:00</updated>\n" +
" <author>\n" +
" <name>AEGIS Wildfhir Server</name>\n" +
" </author>" +
"</feed>";
//@formatter:off
Bundle bundleR = ourCtx.newXmlParser().parseBundle(bundle);
assertEquals(15, bundleR.getTotalResults().getValue().intValue());
}
@Test
public void testEncodeExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
Patient actual = parser.parseResource(Patient.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, ext.size());
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
ResourceReferenceDt ref = actual.getFoo();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeUndeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeBundleResultCount() {
Bundle b = new Bundle();
b.getTotalResults().setValue(123);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">123</os:totalResults>"));
}
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
e.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<category term=\"term\" label=\"label\" scheme=\"scheme\"/>"));
b = ourCtx.newXmlParser().parseBundle(val);
assertEquals(1, b.getEntries().size());
assertEquals(1, b.getEntries().get(0).getCategories().size());
assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm());
assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel());
assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundle() throws InterruptedException {
Bundle b= new Bundle();
b.getCategories().addTag("http://hl7.org/fhir/tag", "http://hl7.org/fhir/tag/message", "Message");
InstantDt pub = InstantDt.withCurrentTime();
b.setPublished(pub);
@ -393,6 +123,7 @@ public class XmlParserTest {
List<String> strings = new ArrayList<String>();
strings.addAll(Arrays.asList("<published>", pub.getValueAsString(), "</published>"));
strings.add("<category term=\"http://hl7.org/fhir/tag/message\" label=\"Message\" scheme=\"http://hl7.org/fhir/tag\"/>");
strings.addAll(Arrays.asList("<entry>", "<id>1</id>", "</entry>"));
strings.addAll(Arrays.asList("<entry>", "<id>2</id>", "<link rel=\"alternate\" href=\"http://foo/bar\"/>", "<link rel=\"search\" href=\"http://foo/bar/search\"/>","</entry>"));
strings.addAll(Arrays.asList("<at:deleted-entry", "ref=\"Patient/3", "/>"));
@ -402,6 +133,44 @@ public class XmlParserTest {
}
@Test
public void testEncodeBundleCategory() {
Bundle b = new Bundle();
BundleEntry e = b.addEntry();
e.setResource(new Patient());
e.addCategory().setLabel("label").setTerm("term").setScheme("scheme");
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<category term=\"term\" label=\"label\" scheme=\"scheme\"/>"));
b = ourCtx.newXmlParser().parseBundle(val);
assertEquals(1, b.getEntries().size());
assertEquals(1, b.getEntries().get(0).getCategories().size());
assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm());
assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel());
assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme());
assertNull(b.getEntries().get(0).getResource());
}
@Test
public void testEncodeBundleResultCount() {
Bundle b = new Bundle();
b.getTotalResults().setValue(123);
String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(val);
assertThat(val, StringContains.containsString("<os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">123</os:totalResults>"));
}
@Test
public void testEncodeContainedAndIncludedResources() {
@ -421,8 +190,6 @@ public class XmlParserTest {
}
@Test
public void testEncodeContainedResources() {
@ -446,6 +213,66 @@ public class XmlParserTest {
}
@Test
public void testEncodeDeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testEncodeDeclaredExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.setFoo(new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
ResourceReferenceDt ref = actual.getFoo();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
Patient actual = parser.parseResource(Patient.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
assertEquals(1, ext.size());
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeInvalidChildGoodException() {
Observation obs = new Observation();
@ -502,6 +329,19 @@ public class XmlParserTest {
}
@Test
public void testEncodeQuery() {
Query q = new Query();
ExtensionDt parameter = q.addParameter();
parameter.setUrl("http://foo").setValue(new StringDt("bar"));
String val = ourCtx.newXmlParser().encodeResourceToString(q);
ourLog.info(val);
assertEquals("<Query xmlns=\"http://hl7.org/fhir\"><parameter url=\"http://foo\"><valueString value=\"bar\"/></parameter></Query>", val);
}
@Test
public void testEncodeResourceRef() throws DataFormatException {
@ -525,6 +365,76 @@ public class XmlParserTest {
}
@Test
public void testEncodeUndeclaredExtensionWithAddressContent() {
IParser parser = ourCtx.newXmlParser();
Patient patient = new Patient();
patient.addAddress().setUse(AddressUseEnum.HOME);
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
String val = parser.encodeResourceToString(patient);
ourLog.info(val);
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
AddressDt ref = actual.getFoo();
assertEquals("line1", ref.getLineFirstRep().getValue());
}
@Test
public void testExtensionOnComposite() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
HumanNameDt given = name.addGiven("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
given.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension><family value=\"Shmoe\"/><given value=\"Joe\"/></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
}
@Test
public void testExtensionOnPrimitive() throws Exception {
Patient patient = new Patient();
HumanNameDt name = patient.addName();
StringDt family = name.addFamily();
family.setValue("Shmoe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
family.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><family value=\"Shmoe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension></family></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
}
@Test
public void testExtensions() throws DataFormatException {
@ -630,6 +540,7 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical());
}
@Test
public void testLoadAndEncodeUndeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException {
IParser p = ourCtx.newXmlParser();
@ -683,25 +594,6 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical());
}
@Test
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
//@formatter:off
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <identifier>\n" +
" <label value=\"IdentifierLabel\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue());
}
@Test
public void testLoadObservation() throws ConfigurationException, DataFormatException, IOException {
@ -767,6 +659,52 @@ public class XmlParserTest {
}
@Test
public void testMoreExtensions() throws Exception {
Patient patient = new Patient();
patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null);
ExtensionDt ext = new ExtensionDt();
ext.setModifier(false);
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.addUndeclaredExtension(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("given"));
given.addUndeclaredExtension(ext2);
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
}
@Test
public void testNarrativeGeneration() throws DataFormatException {
@ -791,12 +729,50 @@ public class XmlParserTest {
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str);
assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass());
assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass());
public void testNestedContainedResources() {
Observation A = new Observation();
A.getName().setText("A");
Observation B = new Observation();
B.getName().setText("B");
A.addRelated().setTarget(new ResourceReferenceDt(B));
Observation C = new Observation();
C.getName().setText("C");
B.addRelated().setTarget(new ResourceReferenceDt(C));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A);
ourLog.info(str);
assertThat(str, stringContainsInOrder(Arrays.asList("<text value=\"B\"/>", "<text value=\"C\"/>", "<text value=\"A\"/>")));
assertThat(str, stringContainsInOrder(Arrays.asList("<contained>", "</contained>")));
// Only one (outer) contained block
int idx0 = str.indexOf("<contained>");
int idx1 = str.indexOf("<contained>",idx0+1);
assertNotEquals(-1, idx0);
assertEquals(-1, idx1);
Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str);
assertEquals("A",obs.getName().getText().getValue());
Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource();
assertEquals("B",obsB.getName().getText().getValue());
Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource();
assertEquals("C",obsC.getName().getText().getValue());
}
@Test
public void testParseBinaryResource() {
Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "<Binary xmlns=\"http://hl7.org/fhir\" contentType=\"foo\">AQIDBA==</Binary>");
assertEquals("foo", val.getContentType());
assertArrayEquals(new byte[] {1,2,3,4}, val.getContent());
}
@SuppressWarnings("deprecation")
@ -814,6 +790,7 @@ public class XmlParserTest {
" <title>FHIR Core Valuesets</title>\n" +
" <id>http://hl7.org/fhir/profile/valuesets</id>\n" +
" <link href=\"http://hl7.org/implement/standards/fhir/valuesets.xml\" rel=\"self\"/>\n" +
" <category term=\"http://hl7.org/fhir/tag/message\" label=\"Message\" scheme=\"http://hl7.org/fhir/tag\"/>\n" +
" <updated>2014-02-10T04:11:24.435-00:00</updated>\n" +
" <entry>\n" +
" <title>Valueset &quot;256a5231-a2bb-49bd-9fea-f349d428b70d&quot; to support automated processing</title>\n" +
@ -867,6 +844,9 @@ public class XmlParserTest {
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Bundle bundle = p.parseBundle(msg);
assertEquals(1, bundle.getCategories().size());
assertEquals("http://hl7.org/fhir/tag", bundle.getCategories().get(0).getScheme());
assertEquals("FHIR Core Valuesets", bundle.getTitle().getValue());
assertEquals("http://hl7.org/implement/standards/fhir/valuesets.xml", bundle.getLinkSelf().getValue());
assertEquals("2014-02-10T04:11:24.435+00:00", bundle.getUpdated().getValueAsString());
@ -946,7 +926,6 @@ public class XmlParserTest {
}
@Test
public void testParseBundleLarge() throws IOException {
@ -961,6 +940,15 @@ public class XmlParserTest {
}
@Test
public void testParseBundleWithMixedReturnTypes() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str);
assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass());
assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass());
}
@Test
public void testParseContainedResources() throws IOException {
@ -976,19 +964,6 @@ public class XmlParserTest {
}
/**
* This sample has extra elements in <searchParam> that are not actually a
* part of the spec any more..
*/
@Test
public void testParseFuroreMetadataWithExtraElements() throws IOException {
String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml"));
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Conformance conf = p.parseResource(Conformance.class, msg);
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
}
@Test
public void testParseEncodeNarrative() {
@ -1010,103 +985,66 @@ public class XmlParserTest {
}
@BeforeClass
public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
ourCtx = new FhirContext();
/**
* This sample has extra elements in <searchParam> that are not actually a
* part of the spec any more..
*/
@Test
public void testParseFuroreMetadataWithExtraElements() throws IOException {
String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml"));
IParser p = new FhirContext(ValueSet.class).newXmlParser();
Conformance conf = p.parseResource(Conformance.class, msg);
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
}
@Test
public void testMoreExtensions() throws Exception {
public void testParseLanguage() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\"><language value=\"zh-CN\"/><text><status value=\"generated\"/><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> 海生 <b>王 </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>URNo</td></tr><tr><td>Address</td><td><span>99 Houston Road </span><br/><span>BENTLEIGH </span><span>Victoria </span></td></tr><tr><td>Date of birth</td><td><span>01 January 1997</span></td></tr></tbody></table></div></text><identifier><use value=\"usual\"/><label value=\"URNo\"/><value value=\"89532\"/></identifier><name><text value=\"王海生\"/><family value=\"\"/><given value=\"海生\"/></name><telecom><system value=\"phone\"/><value value=\"9899 9878\"/><use value=\"home\"/></telecom><telecom><system value=\"email\"/><value value=\"zimmerman@datacorp.com.au\"/><use value=\"home\"/></telecom><gender><coding><system value=\"http://hl7.org/fhir/v3/AdministrativeGender\"/><code value=\"M\"/><display value=\"Male\"/></coding><text value=\"Male\"/></gender><birthDate value=\"1997-01-01\"/><address><use value=\"home\"/><text value=\"99 Houston Road, BENTLEIGH, 3204\"/><line value=\"99 Houston Road\"/><city value=\"BENTLEIGH\"/><state value=\"Victoria\"/><zip value=\"3204\"/><period><start value=\"2006-06-16\"/></period></address><active value=\"true\"/></Patient>";
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
Patient patient = new Patient();
patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null);
ExtensionDt ext = new ExtensionDt();
ext.setModifier(false);
ext.setUrl("http://example.com/extensions#someext");
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
// Add the extension to the resource
patient.addUndeclaredExtension(ext);
// END SNIPPET: resourceExtension
// START SNIPPET: resourceStringExtension
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
StringDt given = name.addGiven();
given.setValue("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("given"));
given.addUndeclaredExtension(ext2);
// END SNIPPET: resourceStringExtension
// START SNIPPET: subExtension
ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent");
patient.addUndeclaredExtension(parent);
ExtensionDt child1 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child1);
ExtensionDt child2 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1"));
parent.addUndeclaredExtension(child2);
// END SNIPPET: subExtension
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertEquals("zh-CN", pt.getLanguage().getValue());
}
@Test
public void testExtensionOnComposite() throws Exception {
public void testParseQuery() {
String msg = "<Query xmlns=\"http://hl7.org/fhir\">\n" +
" <text>\n" +
" <status value=\"generated\"/>\n" +
" <div xmlns=\"http://www.w3.org/1999/xhtml\">[Put rendering here]</div>\n" +
" </text>\n" +
"\n" +
" <!-- this is an extermely simple query - a request to execute the query 'example' on the\n" +
" responder -->\n" +
" <identifier value=\"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\"/>\n" +
" <parameter url=\"http://hl7.org/fhir/query#_query\">\n" +
" <valueString value=\"example\"/>\n" +
" </parameter>\n" +
"</Query>";
Query query = ourCtx.newXmlParser().parseResource(Query.class, msg);
Patient patient = new Patient();
HumanNameDt name = patient.addName();
name.addFamily().setValue("Shmoe");
HumanNameDt given = name.addGiven("Joe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
given.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension><family value=\"Shmoe\"/><given value=\"Joe\"/></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString());
assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString());
assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString());
}
@Test
public void testExtensionOnPrimitive() throws Exception {
public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
Patient patient = new Patient();
HumanNameDt name = patient.addName();
StringDt family = name.addFamily();
family.setValue("Shmoe");
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello"));
family.addUndeclaredExtension(ext2);
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(output);
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<name><family value=\"Shmoe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"Hello\"/></extension></family></name>"));
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc));
assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
//@formatter:off
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <identifier>\n" +
" <label value=\"IdentifierLabel\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue());
}
@Test
@ -1167,4 +1105,71 @@ public class XmlParserTest {
}
@Test
public void testTagList() {
//@formatter:off
String tagListStr = "<taglist xmlns=\"http://hl7.org/fhir\"> \n" +
" <category term=\"term0\" label=\"label0\" scheme=\"scheme0\" /> \n" +
" <category term=\"term1\" label=\"label1\" scheme=\"\" /> \n" +
" <category term=\"term2\" label=\"label2\" /> \n" +
"</taglist>";
//@formatter:on
TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr);
assertEquals(3, tagList.size());
assertEquals("term0", tagList.get(0).getTerm());
assertEquals("label0", tagList.get(0).getLabel());
assertEquals("scheme0", tagList.get(0).getScheme());
assertEquals("term1", tagList.get(1).getTerm());
assertEquals("label1", tagList.get(1).getLabel());
assertEquals(null, tagList.get(1).getScheme());
assertEquals("term2", tagList.get(2).getTerm());
assertEquals("label2", tagList.get(2).getLabel());
assertEquals(null, tagList.get(2).getScheme());
/*
* Encode
*/
//@formatter:off
String expected = "<taglist xmlns=\"http://hl7.org/fhir\">" +
"<category term=\"term0\" label=\"label0\" scheme=\"scheme0\"/>" +
"<category term=\"term1\" label=\"label1\"/>" +
"<category term=\"term2\" label=\"label2\"/>" +
"</taglist>";
//@formatter:on
String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList);
assertEquals(expected,encoded);
}
@Test
public void testTotalResultsUsingOldNamespace() {
//@formatter:off
String bundle = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
" <title>Search results for Patient</title>\n" +
" <id>urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8</id>\n" +
" <totalResults xmlns=\"http://purl.org/atompub/tombstones/1.0\">15</totalResults>\n" +
" <updated>2014-05-04T13:19:47.027-04:00</updated>\n" +
" <author>\n" +
" <name>AEGIS Wildfhir Server</name>\n" +
" </author>" +
"</feed>";
//@formatter:off
Bundle bundleR = ourCtx.newXmlParser().parseBundle(bundle);
assertEquals(15, bundleR.getTotalResults().getValue().intValue());
}
@BeforeClass
public static void beforeClass() {
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
ourCtx = new FhirContext();
}
}

View File

@ -1,9 +1,7 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -581,9 +579,11 @@ public class ClientTest {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
Header[] headers = new Header[2];
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT");
headers[1] = new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333");
Header[] headers = new Header[] {
new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"),
new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
new BasicHeader(Constants.HEADER_CATEGORY, "http://foo/tagdefinition.html; scheme=\"http://hl7.org/fhir/tag\"; label=\"Some tag\"")
};
when(httpResponse.getAllHeaders()).thenReturn(headers);
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
@ -603,6 +603,13 @@ public class ClientTest {
lm.setTimeZoneZulu(true);
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString());
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(response);
assertNotNull(tags);
assertEquals(1,tags.size());
assertEquals("http://foo/tagdefinition.html", tags.get(0).getTerm());
assertEquals("http://hl7.org/fhir/tag",tags.get(0).getScheme());
assertEquals("Some tag",tags.get(0).getLabel());
}
@Test

View File

@ -270,9 +270,11 @@ public class GenericClientTest {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
Header[] headers = new Header[2];
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT");
headers[1] = new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333");
Header[] headers = new Header[] {
new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"),
new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
new BasicHeader(Constants.HEADER_CATEGORY, "http://foo/tagdefinition.html; scheme=\"http://hl7.org/fhir/tag\"; label=\"Some tag\"")
};
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
@ -289,6 +291,13 @@ public class GenericClientTest {
lm.setTimeZoneZulu(true);
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString());
TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(response);
assertNotNull(tags);
assertEquals(1,tags.size());
assertEquals("http://foo/tagdefinition.html", tags.get(0).getTerm());
assertEquals("http://hl7.org/fhir/tag",tags.get(0).getScheme());
assertEquals("Some tag",tags.get(0).getLabel());
}
@SuppressWarnings("unused")

View File

@ -75,7 +75,7 @@ public class TransactionClientTest {
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
client.searchWithParam(resources);
client.transaction(resources);
assertEquals(HttpPost.class, capt.getValue().getClass());
HttpPost post = (HttpPost) capt.getValue();
@ -92,6 +92,47 @@ public class TransactionClientTest {
assertTrue(bundle.getEntries().get(1).getId().isEmpty());
}
@Test
public void testSimpleTransactionWithBundleParam() throws Exception {
Patient patient = new Patient();
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
patient.addIdentifier("urn:system", "testPersistWithSimpleLinkP01");
patient.addName().addFamily("Tester").addGiven("Joe");
Observation obs = new Observation();
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
Bundle transactionBundle = Bundle.withResources(Arrays.asList((IResource)patient, obs), ctx, "http://foo");
IBundleClient client = ctx.newRestfulClient(IBundleClient.class, "http://foo");
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
client.transaction(transactionBundle);
assertEquals(HttpPost.class, capt.getValue().getClass());
HttpPost post = (HttpPost) capt.getValue();
assertEquals("http://foo/", post.getURI().toString());
Bundle bundle = ctx.newXmlParser().parseBundle(new InputStreamReader(post.getEntity().getContent()));
ourLog.info(ctx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle));
assertEquals(2, bundle.size());
assertEquals("http://foo/Patient/testPersistWithSimpleLinkP01", bundle.getEntries().get(0).getId().getValue());
assertEquals("http://foo/Patient/testPersistWithSimpleLinkP01", bundle.getEntries().get(0).getLinkSelf().getValue());
assertEquals(null, bundle.getEntries().get(0).getLinkAlternate().getValue());
assertTrue(bundle.getEntries().get(1).getId().isEmpty());
}
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionClientTest.class);
private String createBundle() {
return ctx.newXmlParser().encodeBundleToString(new Bundle());
@ -100,7 +141,15 @@ public class TransactionClientTest {
private interface IClient extends IBasicClient {
@Transaction
public List<IResource> searchWithParam(@TransactionParam List<IResource> theResources);
public List<IResource> transaction(@TransactionParam List<IResource> theResources);
}
private interface IBundleClient extends IBasicClient {
@Transaction
public List<IResource> transaction(@TransactionParam Bundle theResources);
}

View File

@ -14,7 +14,7 @@ public class BaseOutcomeReturningMethodBindingTest {
String headerString = "http://britsystems.com/fhir/tag/4567; scheme=\"http://britsystems.com/fhir\"; label=\"Tag-4567\",http://client/scheme/tag/123; scheme=\"http://client/scheme\"; label=\"tag 123\",http://client/scheme/tag/456; scheme=\"http://client/scheme\"; label=\"tag 456\",http://fhir.healthintersections.com.au/open/Patient/1; scheme=\"http://hl7.org/fhir/tag\"; label=\"GET <host>/<resourceType>/<id>\",http://hl7.fhir/example; scheme=\"http://hl7.org/fhir/tag\"; label=\"FHIR example\",http://hl7.org/fhir/sid/us-ssn; scheme=\"http://hl7.org/fhir/tag\"; label=\"POST <host>/<resourceType>\",http://hl7.org/fhir/tools/tag/test; scheme=\"http://hl7.org/fhir/tag\"; label=\"Test Tag\",http://hl7.org/implement/standards/fhir/v3/ActCode/InformationSensitivityPolicy#GDIS; scheme=\"http://hl7.org/fhir/tag\"; label=\"GDIS\",http://hl7.org/implement/standards/fhir/v3/Confidentiality#N; scheme=\"http://hl7.org/fhir/tag\"; label=\"N (Normal)\",http://hl7.org/implement/standards/fhir/v3/Confidentiality#R; scheme=\"http://hl7.org/fhir/tag\"; label=\"restricted\",http://nu.nl/testname; scheme=\"http://hl7.org/fhir/tag\"; label=\"TestCreateEditDelete\",http://readtag.nu.nl; scheme=\"http://hl7.org/fhir/tag\"; label=\"readTagTest\",http://spark.furore.com/fhir; scheme=\"http://hl7.org/fhir/tag\"; label=\"GET <host>/<resourceType>/<id>\",http://www.healthintersections.com.au/fhir/tags/invalid; scheme=\"http://hl7.org/fhir/tag\"; label=\"Non-conformant Resource\",urn:happytag; scheme=\"http://hl7.org/fhir/tag\"; label=\"This is a happy resource\",condition; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile condition\",device; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile device\",http://fhir.healthintersections.com.au/open/Profile/condition; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile condition\",http://fhir.healthintersections.com.au/open/Profile/device; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile device\",http://hl7.org/fhir/v3/ActCode#CEL; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Celebrity / VIP\",http://hl7.org/fhir/v3/ActCode#DEMO; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Contact/Employment Confidential\",http://hl7.org/fhir/v3/ActCode#DIA; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Diagnosis is/would be Confidential\",http://hl7.org/fhir/v3/ActCode#EMP; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Employee / Staff member\",http://hl7.org/fhir/v3/ActCode#ORCON; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Author only\",http://hl7.org/fhir/v3/ActCode#TABOO; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Patient/Carer Only\",http://hl7.org/fhir/v3/Confidentiality#L; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Low\",http://hl7.org/fhir/v3/Confidentiality#M; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Moderate\",http://hl7.org/fhir/v3/Confidentiality#N; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Normal\",http://hl7.org/fhir/v3/Confidentiality#R; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Restricted\",http://hl7.org/fhir/v3/Confidentiality#U; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = none\",http://hl7.org/fhir/v3/Confidentiality#V; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Very Restricted\",http://term.com; scheme=\"http://scheme.com\"; label=\"Some good ole term\"";
TagList parsedFromHeader = new TagList();
BaseOutcomeReturningMethodBinding.parseTagValue(parsedFromHeader, headerString);
MethodUtil.parseTagValue(parsedFromHeader, headerString);
//@formatter:off
String resourceString = "{\n" +

View File

@ -63,7 +63,7 @@ public class CustomTypeTest {
assertEquals(1, bundle.getEntries().size());
BundleEntry entry = bundle.getEntries().get(0);
ArrayList<Tag> profileTags = entry.getCategories().getTagsWithScheme(Constants.TAG_SCHEME_PROFILE);
List<Tag> profileTags = entry.getCategories().getTagsWithScheme(Tag.HL7_ORG_PROFILE_TAG);
assertEquals(1, profileTags.size());
assertEquals("http://foo/profiles/Profile", profileTags.get(0).getTerm());

View File

@ -10,6 +10,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
@ -26,9 +27,11 @@ import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RequiredParam;
@ -149,6 +152,29 @@ public class SearchTest {
assertEquals("AAANamed", p.getIdentifierFirstRep().getValue().getValue());
}
@Test
public void testReturnLinks() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort+"/Patient?_query=findWithLinks");
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.getEntries().size());
Patient p = bundle.getResources(Patient.class).get(0);
assertEquals("AAANamed", p.getIdentifierFirstRep().getValue().getValue());
assertEquals("http://foo/Patient?_id=1", bundle.getEntries().get(0).getLinkSearch().getValue());
assertEquals("http://localhost:" + ourPort+"/Patient/9988", bundle.getEntries().get(0).getLinkAlternate().getValue());
assertEquals("http://foo/Patient?_id=1", ResourceMetadataKeyEnum.LINK_SEARCH.get(p));
assertEquals("http://localhost:" + ourPort+"/Patient/9988", ResourceMetadataKeyEnum.LINK_ALTERNATE.get(p));
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
@ -206,7 +232,7 @@ public class SearchTest {
public static class DummyPatientResourceProvider implements IResourceProvider {
@Search
public List<Patient> findPatient(@OptionalParam(name = "_id") StringParam theParam) {
public List<Patient> findPatient(@RequiredParam(name = "_id") StringParam theParam) {
ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient patient = new Patient();
@ -220,7 +246,7 @@ public class SearchTest {
}
@Search
public List<Patient> findPatientByAAA01(@OptionalParam(name = "AAA") StringParam theParam) {
public List<Patient> findPatientByAAA01(@RequiredParam(name = "AAA") StringParam theParam) {
ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient patient = new Patient();
@ -241,6 +267,19 @@ public class SearchTest {
return retVal;
}
@Search(queryName="findWithLinks")
public List<Patient> findWithLinks() {
ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient patient = new Patient();
patient.setId("1");
patient.addIdentifier("system", "AAANamed");
ResourceMetadataKeyEnum.LINK_SEARCH.put(patient, ("http://foo/Patient?_id=1"));
ResourceMetadataKeyEnum.LINK_ALTERNATE.put(patient, ("Patient/9988"));
retVal.add(patient);
return retVal;
}
@Override
public Class<? extends IResource> getResourceType() {
return Patient.class;

View File

@ -41,17 +41,16 @@ public class TransactionTest {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = new FhirContext();
private static boolean ourDropFirstResource;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionTest.class);
private static int ourPort;
private static boolean ourReturnOperationOutcome;
private static Server ourServer;
@Before
public void before() {
ourReturnOperationOutcome = false;
ourDropFirstResource = false;
}
@Test
@ -82,7 +81,8 @@ public class TransactionTest {
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
@ -105,8 +105,58 @@ public class TransactionTest {
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
}
}
@Test
public void testTransactionWithFewerResponseElements() throws Exception {
ourDropFirstResource =true;
Bundle b = new Bundle();
InstantDt nowInstant = InstantDt.withCurrentTime();
Patient p1 = new Patient();
p1.addName().addFamily("Family1");
BundleEntry entry = b.addEntry();
entry.getId().setValue("1");
entry.setResource(p1);
Patient p2 = new Patient();
p2.addName().addFamily("Family2");
entry = b.addEntry();
entry.getId().setValue("2");
entry.setResource(p2);
BundleEntry deletedEntry = b.addEntry();
deletedEntry.setId(new IdDt("Patient/3"));
deletedEntry.setDeleted(nowInstant);
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(bundleString);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
ourLog.info(responseContent);
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(2, bundle.size());
BundleEntry entry1 = bundle.getEntries().get(0);
assertEquals("http://localhost:" + ourPort + "/Patient/82", entry1.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/82/_history/92", entry1.getLinkSelf().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/2", entry1.getLinkAlternate().getValue());
BundleEntry entry2 = bundle.getEntries().get(1);
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
}
@Test
public void testTransactionWithOperationOutcome() throws Exception {
@ -138,7 +188,8 @@ public class TransactionTest {
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
@ -164,7 +215,7 @@ public class TransactionTest {
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
}
}
@AfterClass
public static void afterClass() throws Exception {
@ -200,33 +251,35 @@ public class TransactionTest {
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyProvider {
public static class DummyProvider {
@Transaction
public List<IResource> transaction(@TransactionParam List<IResource> theResources) {
int index=1;
int index = 1;
for (IResource next : theResources) {
String newId = "8"+Integer.toString(index);
String newId = "8" + Integer.toString(index);
if (next.getResourceMetadata().containsKey(ResourceMetadataKeyEnum.DELETED_AT)) {
newId = next.getId().getIdPart();
}
next.setId(new IdDt("Patient", newId, "9"+Integer.toString(index)));
next.setId(new IdDt("Patient", newId, "9" + Integer.toString(index)));
index++;
}
List<IResource> retVal = theResources;
List<IResource> retVal = new ArrayList<IResource>(theResources);
if (ourDropFirstResource) {
retVal.remove(0);
}
if (ourReturnOperationOutcome) {
retVal = new ArrayList<IResource>();
OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDetails("AAAAA");
retVal.add(oo);
retVal.addAll(theResources);
retVal.add(0, oo);
}
return retVal;
}
}
}

View File

@ -0,0 +1,234 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class TransactionWithBundleParamTest {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = new FhirContext();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionWithBundleParamTest.class);
private static int ourPort;
private static boolean ourReturnOperationOutcome;
private static Server ourServer;
@Before
public void before() {
ourReturnOperationOutcome = false;
}
@Test
public void testTransaction() throws Exception {
Bundle b = new Bundle();
InstantDt nowInstant = InstantDt.withCurrentTime();
Patient p1 = new Patient();
p1.addName().addFamily("Family1");
BundleEntry entry = b.addEntry();
entry.getId().setValue("1");
entry.setResource(p1);
Patient p2 = new Patient();
p2.addName().addFamily("Family2");
entry = b.addEntry();
entry.getId().setValue("2");
entry.setResource(p2);
BundleEntry deletedEntry = b.addEntry();
deletedEntry.setId(new IdDt("Patient/3"));
deletedEntry.setDeleted(nowInstant);
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(bundleString);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
ourLog.info(responseContent);
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(3, bundle.size());
BundleEntry entry0 = bundle.getEntries().get(0);
assertEquals("http://localhost:" + ourPort + "/Patient/81", entry0.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/81/_history/91", entry0.getLinkSelf().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkAlternate().getValue());
BundleEntry entry1 = bundle.getEntries().get(1);
assertEquals("http://localhost:" + ourPort + "/Patient/82", entry1.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/82/_history/92", entry1.getLinkSelf().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/2", entry1.getLinkAlternate().getValue());
BundleEntry entry2 = bundle.getEntries().get(2);
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
}
@Test
public void testTransactionWithOperationOutcome() throws Exception {
ourReturnOperationOutcome = true;
Bundle b = new Bundle();
InstantDt nowInstant = InstantDt.withCurrentTime();
Patient p1 = new Patient();
p1.addName().addFamily("Family1");
BundleEntry entry = b.addEntry();
entry.getId().setValue("1");
entry.setResource(p1);
Patient p2 = new Patient();
p2.addName().addFamily("Family2");
entry = b.addEntry();
entry.getId().setValue("2");
entry.setResource(p2);
BundleEntry deletedEntry = b.addEntry();
deletedEntry.setId(new IdDt("Patient/3"));
deletedEntry.setDeleted(nowInstant);
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
ourLog.info(bundleString);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
ourLog.info(responseContent);
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(4, bundle.size());
assertEquals(OperationOutcome.class, bundle.getEntries().get(0).getResource().getClass());
assertEquals("OperationOutcome (no ID)", bundle.getEntries().get(0).getTitle().getValue());
BundleEntry entry0 = bundle.getEntries().get(1);
assertEquals("http://localhost:" + ourPort + "/Patient/81", entry0.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/81/_history/91", entry0.getLinkSelf().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkAlternate().getValue());
BundleEntry entry1 = bundle.getEntries().get(2);
assertEquals("http://localhost:" + ourPort + "/Patient/82", entry1.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/82/_history/92", entry1.getLinkSelf().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/2", entry1.getLinkAlternate().getValue());
BundleEntry entry2 = bundle.getEntries().get(3);
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ourServer = new Server(ourPort);
DummyProvider patientProvider = new DummyProvider();
RestfulServer server = new RestfulServer();
server.setProviders(patientProvider);
org.eclipse.jetty.servlet.ServletContextHandler proxyHandler = new org.eclipse.jetty.servlet.ServletContextHandler();
proxyHandler.setContextPath("/");
ServletHolder handler = new ServletHolder();
handler.setServlet(server);
proxyHandler.addServlet(handler, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyProvider {
@Transaction
public List<IResource> transaction(@TransactionParam Bundle theResources) {
int index=1;
for (IResource next : theResources.toListOfResources()) {
String newId = "8"+Integer.toString(index);
if (next.getResourceMetadata().containsKey(ResourceMetadataKeyEnum.DELETED_AT)) {
newId = next.getId().getIdPart();
}
next.setId(new IdDt("Patient", newId, "9"+Integer.toString(index)));
index++;
}
List<IResource> retVal = theResources.toListOfResources();
if (ourReturnOperationOutcome) {
retVal = new ArrayList<IResource>();
OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDetails("AAAAA");
retVal.add(oo);
retVal.addAll(theResources.toListOfResources());
}
return retVal;
}
}
}

View File

@ -25,6 +25,11 @@
}
],
"updated" : "2014-03-22T15:37:12Z",
"category" : [{
"term" : "http://term",
"label" : "label",
"scheme" : "http://scheme"
}],
"totalResults" : "356",
"entry" : [
{

View File

@ -12,7 +12,7 @@
<dependent-module archiveName="hapi-fhir-base-0.6-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-testpage-overlay?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependent-module deploy-path="/" handle="module:/overlay/var/M2_REPO/ca/uhn/hapi/fhir/hapi-fhir-testpage-overlay/0.6-SNAPSHOT/hapi-fhir-testpage-overlay-0.6-SNAPSHOT.war?unpackFolder=target/m2e-wtp/overlays&amp;includes=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependency-type>consumes</dependency-type>
</dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">

View File

@ -110,6 +110,7 @@ public class TinderStructuresMojo extends AbstractMojo {
ourLog.info("Loading profiles...");
ProfileParser pp = new ProfileParser();
for (ProfileFileDefinition next : resourceProfileFiles) {
ourLog.info("Parsing file: {}", next.profileFile);
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl);
}
@ -182,6 +183,10 @@ public class TinderStructuresMojo extends AbstractMojo {
public static void main(String[] args) throws Exception {
ProfileParser pp = new ProfileParser();
pp.parseSingleProfile(new File("../hapi-tinder-test/src/test/resources/profile/patient.xml"), "http://foo");
ValueSetGenerator vsp = new ValueSetGenerator();
// vsp.setDirectory("src/test/resources/vs/");
vsp.parse();
@ -194,8 +199,9 @@ public class TinderStructuresMojo extends AbstractMojo {
dtp.writeAll(new File(dtOutputDir), "ca.uhn.fhir.model.dstu");
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
rp.setBaseResourceNames(Arrays.asList("observation"));
rp.setBaseResourceNames(Arrays.asList("patient"));
rp.parse();
// rp.bindValueSets(vsp);
String rpOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/resource";

View File

@ -57,6 +57,7 @@
<modules>
<module>hapi-fhir-base</module>
<module>hapi-fhir-base/examples</module>
<module>hapi-tinder-plugin</module>
<module>hapi-tinder-test</module>
<module>hapi-fhir-structures-dstu</module>