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 { public class GenericClientExample {
@SuppressWarnings("unused")
public static void simpleExample() { public static void simpleExample() {
// START SNIPPET: simple // START SNIPPET: simple
FhirContext ctx = new FhirContext(); FhirContext ctx = new FhirContext();
String serverBase = "http://fhir.healthintersections.com.au/open"; String serverBase = "http://fhirtest.uhn.ca/base";
IGenericClient client = ctx.newRestfulGenericClient(serverBase); IGenericClient client = ctx.newRestfulGenericClient(serverBase);
// Read a patient // Perform a search
Patient patient = client.read(Patient.class, "1"); Bundle results = client.search()
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value("duck"))
.execute();
// Change the patient and update it to the server System.out.println("Found " + results.size() + " patients named 'duck'");
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);
// END SNIPPET: simple // END SNIPPET: simple
} }
@ -177,7 +174,7 @@ List<IResource> response = client.transaction()
} }
public static void main(String[] args) { 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.TagList;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.api.annotation.Description; 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.composite.CodingDt;
import ca.uhn.fhir.model.dstu.resource.Conformance; import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport; 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.MethodOutcome;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; 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.IBasicClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient; import ca.uhn.fhir.rest.client.api.IRestfulClient;
import ca.uhn.fhir.rest.param.CompositeParam; import ca.uhn.fhir.rest.param.CompositeParam;
@ -78,6 +77,14 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public abstract class RestfulPatientResourceProviderMore implements IResourceProvider { 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 detectedVersionConflict;
private boolean conflictHappened; private boolean conflictHappened;
private boolean couldntFindThisId; 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> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId> <artifactId>hapi-fhir-base</artifactId>
<packaging>jar</packaging> <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> <name>HAPI FHIR - Core Library</name>
@ -20,14 +20,11 @@
<id>git.server</id> <id>git.server</id>
<url>scm:git:git@github.com:jamesagnew/hapi-fhir.git</url> <url>scm:git:git@github.com:jamesagnew/hapi-fhir.git</url>
</site> </site>
<!-- <site> <id>hl7api.sf.net</id> <url>scp://shell.sourceforge.net/home/project-web/hl7api/htdocs/hapi-fhir</url> </site> -->
</distributionManagement> </distributionManagement>
<dependencies> <dependencies>
<!-- JSON --> <!-- JSON -->
<!-- <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.2.4</version> </dependency> -->
<dependency> <dependency>
<groupId>javax.json</groupId> <groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId> <artifactId>javax.json-api</artifactId>

View File

@ -7,9 +7,11 @@
</properties> </properties>
<body> <body>
<release version="0.6" date="TBD"> <release version="0.6" date="TBD">
<!--
<action type="add"> <action type="add">
Allow generic client ... OAUTH Allow generic client ... OAUTH
</action> </action>
-->
<action type="fix"> <action type="fix">
Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University
Health Network for reporting! 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 is "yyyy-mm-dd" anyhow, and this is correctly handled). Thanks to Jeffrey Ting of Systems Made Simple
for reporting! for reporting!
</action> </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"> <action type="fix">
Server search method for an unnamed query gets called if the client requests a named query 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! with the same parameter list. Thanks to Neal Acharya of University Health Network for reporting!
</action> </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>
<release version="0.5" date="2014-Jul-30"> <release version="0.5" date="2014-Jul-30">
<action type="add"> <action type="add">

View File

@ -204,8 +204,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
if (values == null) { if (values == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
@SuppressWarnings("unchecked") List<? extends IElement> retVal = (List<? extends IElement>) Collections.singletonList((IElement)values);
List<? extends IElement> retVal = (List<? extends IElement>) Collections.singletonList(values);
return retVal; return retVal;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new ConfigurationException("Failed to get value", e); throw new ConfigurationException("Failed to get value", e);

View File

@ -585,24 +585,36 @@ class ModelScanner {
private String scanResource(Class<? extends IResource> theClass, ResourceDef resourceDefinition) { private String scanResource(Class<? extends IResource> theClass, ResourceDef resourceDefinition) {
ourLog.debug("Scanning resource class: {}", theClass.getName()); ourLog.debug("Scanning resource class: {}", theClass.getName());
boolean primaryNameProvider = true;
String resourceName = resourceDefinition.name(); String resourceName = resourceDefinition.name();
if (isBlank(resourceName)) { if (isBlank(resourceName)) {
throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name: " + theClass.getCanonicalName()); 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.containsKey(resourceName)) {
if (!myNameToResourceDefinitions.get(resourceName).getImplementingClass().equals(theClass)) { // if (!myNameToResourceDefinitions.get(resourceName).getImplementingClass().equals(theClass)) {
// throw new // // throw new
// ConfigurationException("Detected duplicate element name '" + // // ConfigurationException("Detected duplicate element name '" +
// resourceName + "' in types '" + theClass.getCanonicalName() + // // resourceName + "' in types '" + theClass.getCanonicalName() +
// "' and '" // // "' and '"
// + // // +
// myNameToResourceDefinitions.get(resourceName).getImplementingClass() // // myNameToResourceDefinitions.get(resourceName).getImplementingClass()
// + "'"); // // + "'");
} else { // } else {
return resourceName; // return resourceName;
} // }
} // }
String resourceId = resourceDefinition.id(); String resourceId = resourceDefinition.id();
if (isBlank(resourceId)) { if (isBlank(resourceId)) {
@ -619,10 +631,11 @@ class ModelScanner {
String profile = resourceDefinition.profile(); String profile = resourceDefinition.profile();
RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(theClass, resourceDefinition); RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(resourceName, theClass, resourceDefinition);
myClassToElementDefinitions.put(theClass, resourceDef); myClassToElementDefinitions.put(theClass, resourceDef);
if (primaryNameProvider) {
myNameToResourceDefinitions.put(resourceName, resourceDef); myNameToResourceDefinitions.put(resourceName, resourceDef);
}
scanCompositeElementForChildren(theClass, resourceDef); scanCompositeElementForChildren(theClass, resourceDef);
myIdToResourceDefinition.put(resourceId, 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.IResource;
import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefinition { public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefinition {
@ -103,6 +104,11 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
if (alternateElementName != null) { if (alternateElementName != null) {
myNameToChildDefinition.put(alternateElementName, nextDef); myNameToChildDefinition.put(alternateElementName, nextDef);
} }
if (IResource.class.isAssignableFrom(next)) {
myDatatypeToElementDefinition.put(ResourceReferenceDt.class, nextDef);
}
myDatatypeToElementDefinition.put(next, nextDef); myDatatypeToElementDefinition.put(next, nextDef);
myDatatypeToElementName.put(next, elementName); myDatatypeToElementName.put(next, elementName);
} }

View File

@ -60,8 +60,8 @@ public class RuntimeResourceDefinition extends BaseRuntimeElementCompositeDefini
private List<RuntimeSearchParam> mySearchParams; private List<RuntimeSearchParam> mySearchParams;
private String myId; private String myId;
public RuntimeResourceDefinition(Class<? extends IResource> theClass, ResourceDef theResourceAnnotation) { public RuntimeResourceDefinition(String theResourceName, Class<? extends IResource> theClass, ResourceDef theResourceAnnotation) {
super(theResourceAnnotation.name(), theClass); super(theResourceName, theClass);
myResourceProfile = theResourceAnnotation.profile(); myResourceProfile = theResourceAnnotation.profile();
myId = theResourceAnnotation.id(); myId = theResourceAnnotation.id();
} }

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.model.api;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; 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.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.UrlUtil;
public class Bundle extends BaseBundle /* implements IElement */{ public class Bundle extends BaseBundle /* implements IElement */{
private volatile transient Map<IdDt, IResource> myIdToEntries; 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 List<BundleEntry> myEntries;
private StringDt myBundleId; private StringDt myBundleId;
private StringDt myLinkBase; private StringDt myLinkBase;
@ -60,6 +56,7 @@ public class Bundle extends BaseBundle /* implements IElement */{
private StringDt myTitle; private StringDt myTitle;
private IntegerDt myTotalResults; private IntegerDt myTotalResults;
private InstantDt myUpdated; private InstantDt myUpdated;
private TagList myCategories;
/** /**
* Returns true if this bundle contains zero entries * Returns true if this bundle contains zero entries
@ -69,6 +66,16 @@ public class Bundle extends BaseBundle /* implements IElement */{
return getEntries().isEmpty(); 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 * 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. * Retrieves a resource from a bundle given its logical ID.
* <p> * <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 * <b>Important usage notes</b>: This method ignores base URLs (so passing in an 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 * <code>http://foo/Patient/123</code> will return a resource if it has the logical ID of
* modifications to the bundle after this method is called may not be accurately reflected. * <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> * </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 * @return Returns the resource with the given ID, or <code>null</code> if none is found
*/ */
public IResource getResourceById(IdDt theId) { public IResource getResourceById(IdDt theId) {
@ -128,6 +138,18 @@ public class Bundle extends BaseBundle /* implements IElement */{
// c.update().resource(txt).withId("1665").execute(); // 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() { public List<BundleEntry> getEntries() {
if (myEntries == null) { if (myEntries == null) {
myEntries = new ArrayList<BundleEntry>(); myEntries = new ArrayList<BundleEntry>();
@ -269,8 +291,6 @@ public class Bundle extends BaseBundle /* implements IElement */{
BundleEntry entry = addEntry(); BundleEntry entry = addEntry();
entry.setResource(theResource); entry.setResource(theResource);
entry.setResource(theResource);
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource); RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);
String title = ResourceMetadataKeyEnum.TITLE.get(theResource); String title = ResourceMetadataKeyEnum.TITLE.get(theResource);
@ -312,6 +332,24 @@ public class Bundle extends BaseBundle /* implements IElement */{
String qualifiedId = b.toString(); String qualifiedId = b.toString();
entry.getLinkSelf().setValue(qualifiedId); 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); InstantDt published = ResourceMetadataKeyEnum.PUBLISHED.get(theResource);
@ -346,9 +384,9 @@ public class Bundle extends BaseBundle /* implements IElement */{
return entry; 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(); Bundle retVal = new Bundle();
for (IResource next : theUploadBundle) { for (IResource next : theResources) {
retVal.addResource(next, theContext, theServerBase); retVal.addResource(next, theContext, theServerBase);
} }
return retVal; 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; private final String myValue;
public ResourceMetadataKeyEnum(String theValue) { 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"; 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_TERM = "term";
public static final String ATTR_LABEL = "label"; public static final String ATTR_LABEL = "label";
public static final String ATTR_SCHEME = "scheme"; 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.ArrayList;
import java.util.List;
public class TagList extends ArrayList<Tag> { public class TagList extends ArrayList<Tag> {
@ -48,7 +49,7 @@ public class TagList extends ArrayList<Tag> {
return null; return null;
} }
public ArrayList<Tag> getTagsWithScheme(String theScheme) { public List<Tag> getTagsWithScheme(String theScheme) {
ArrayList<Tag> retVal = new ArrayList<Tag>(); ArrayList<Tag> retVal = new ArrayList<Tag>();
for (Tag next : this) { for (Tag next : this) {
if (theScheme.equals(next.getScheme())) { if (theScheme.equals(next.getScheme())) {

View File

@ -35,7 +35,7 @@ public @interface ResourceDef {
/** /**
* The name of the resource (e.g. "Patient" or "DiagnosticReport") * The name of the resource (e.g. "Patient" or "DiagnosticReport")
*/ */
String name(); String name() default "";
/** /**
* Not currently used * 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.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.Constants; 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, * 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()); 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 * Returns <code>true</code> if the unqualified ID is a valid {@link Long} value (in other words, it consists only
* of digits) * of digits)

View File

@ -1,5 +1,25 @@
package ca.uhn.fhir.model.view; 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 java.util.List;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeChildDefinition;

View File

@ -167,6 +167,8 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.writeEnd(); eventWriter.writeEnd();
} }
writeCategories(eventWriter, theBundle.getCategories());
writeOptionalTagWithTextNode(eventWriter, "totalResults", theBundle.getTotalResults()); writeOptionalTagWithTextNode(eventWriter, "totalResults", theBundle.getTotalResults());
writeAuthor(theBundle, eventWriter); writeAuthor(theBundle, eventWriter);
@ -193,17 +195,7 @@ public class JsonParser extends BaseParser implements IParser {
writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated()); writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished()); writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
if (nextEntry.getCategories() != null && nextEntry.getCategories().size() > 0) { writeCategories(eventWriter, nextEntry.getCategories());
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();
}
writeAuthor(nextEntry, eventWriter); writeAuthor(nextEntry, eventWriter);
@ -221,6 +213,20 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.flush(); 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, private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
String theChildName) throws IOException { String theChildName) throws IOException {
@ -291,10 +297,10 @@ public class JsonParser extends BaseParser implements IParser {
} }
if (StringUtils.isNotBlank(reference)) { if (StringUtils.isNotBlank(reference)) {
theWriter.write("resource", reference); theWriter.write(XmlParser.RESREF_REFERENCE, reference);
} }
if (referenceDt.getDisplay().isEmpty() == false) { if (referenceDt.getDisplay().isEmpty() == false) {
theWriter.write("display", referenceDt.getDisplay().getValueAsString()); theWriter.write(XmlParser.RESREF_DISPLAY, referenceDt.getDisplay().getValueAsString());
} }
theWriter.writeEnd(); theWriter.writeEnd();
break; break;

View File

@ -20,8 +20,7 @@ package ca.uhn.fhir.parser;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.defaultIfBlank; import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; 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.InstantDt;
import ca.uhn.fhir.model.primitive.XhtmlDt; import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.util.IModelVisitor;
class ParserState<T> { class ParserState<T> {
@ -474,6 +474,12 @@ class ParserState<T> {
metadata.put(ResourceMetadataKeyEnum.VERSION_ID, linkSelf); 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())); push(new AtomPrimitiveState(myInstance.getUpdated()));
} else if ("author".equals(theLocalPart)) { } else if ("author".equals(theLocalPart)) {
push(new AtomAuthorState(myInstance)); 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)) { } else if ("deleted-entry".equals(theLocalPart) && verifyNamespace(XmlParser.TOMBSTONES_NS, theNamespaceURI)) {
push(new AtomDeletedEntryState(myInstance, myResourceType)); push(new AtomDeletedEntryState(myInstance, myResourceType));
} else { } else {
@ -902,7 +910,7 @@ class ParserState<T> {
public void attributeValue(String theName, String theValue) throws DataFormatException { public void attributeValue(String theName, String theValue) throws DataFormatException {
if ("id".equals(theName)) { if ("id".equals(theName)) {
if (myInstance instanceof IIdentifiableElement) { if (myInstance instanceof IIdentifiableElement) {
((IIdentifiableElement) myInstance).setId(new IdDt(theValue)); ((IIdentifiableElement) myInstance).setElementSpecificId((theValue));
} else if (myInstance instanceof IResource) { } else if (myInstance instanceof IResource) {
((IResource) myInstance).setId(new IdDt(theValue)); ((IResource) myInstance).setId(new IdDt(theValue));
} }
@ -1249,7 +1257,17 @@ class ParserState<T> {
myObject = (T) myInstance; myObject = (T) myInstance;
} }
for (ResourceReferenceDt nextRef : myResourceReferences) { 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(); String ref = nextRef.getReference().getValue();
if (isNotBlank(ref)) { if (isNotBlank(ref)) {
if (ref.startsWith("#")) { if (ref.startsWith("#")) {
@ -1262,6 +1280,8 @@ class ParserState<T> {
} }
} }
} }
}
});
} }

View File

@ -80,6 +80,8 @@ import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
import ca.uhn.fhir.util.PrettyPrintWriterWrapper; import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
public class XmlParser extends BaseParser implements IParser { 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); 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 ATOM_NS = "http://www.w3.org/2005/Atom";
static final String FHIR_NS = "http://hl7.org/fhir"; static final String FHIR_NS = "http://hl7.org/fhir";
@ -144,6 +146,8 @@ public class XmlParser extends BaseParser implements IParser {
eventWriter.writeEndElement(); eventWriter.writeEndElement();
} }
writeCategories(eventWriter, theBundle.getCategories());
for (BundleEntry nextEntry : theBundle.getEntries()) { for (BundleEntry nextEntry : theBundle.getEntries()) {
boolean deleted = false; boolean deleted = false;
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == 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, "updated", nextEntry.getUpdated());
writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished()); writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());
if (nextEntry.getCategories() != null) { writeCategories(eventWriter, nextEntry.getCategories());
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();
}
}
if (!nextEntry.getLinkSelf().isEmpty()) { if (!nextEntry.getLinkSelf().isEmpty()) {
writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf()); 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 @Override
public String encodeResourceToString(IResource theResource) throws DataFormatException { public String encodeResourceToString(IResource theResource) throws DataFormatException {
if (theResource == null) { if (theResource == null) {
@ -550,12 +558,12 @@ public class XmlParser extends BaseParser implements IParser {
// } // }
if (!(theRef.getDisplay().isEmpty())) { if (!(theRef.getDisplay().isEmpty())) {
theEventWriter.writeStartElement("display"); theEventWriter.writeStartElement(RESREF_DISPLAY);
theEventWriter.writeAttribute("value", theRef.getDisplay().getValue()); theEventWriter.writeAttribute("value", theRef.getDisplay().getValue());
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} }
if (StringUtils.isNotBlank(reference)) { if (StringUtils.isNotBlank(reference)) {
theEventWriter.writeStartElement("reference"); theEventWriter.writeStartElement(RESREF_REFERENCE);
theEventWriter.writeAttribute("value", reference); theEventWriter.writeAttribute("value", reference);
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} }

View File

@ -24,7 +24,15 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 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) @Target(value=ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface TransactionParam { public @interface TransactionParam {

View File

@ -20,8 +20,6 @@ package ca.uhn.fhir.rest.method;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
@ -39,7 +37,6 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; 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.api.TagList;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum; import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt; 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; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> { abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
private static final String LABEL = "label=\"";
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class); static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
private static final String SCHEME = "scheme=\"";
private boolean myReturnVoid; private boolean myReturnVoid;
@ -118,7 +113,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
TagList tagList = new TagList(); TagList tagList = new TagList();
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) { for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
String nextTagComplete = enumeration.nextElement(); String nextTagComplete = enumeration.nextElement();
parseTagValue(tagList, nextTagComplete); MethodUtil.parseTagValue(tagList, nextTagComplete);
} }
if (tagList.isEmpty() == false) { if (tagList.isEmpty() == false) {
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList); resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
@ -218,19 +213,25 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
// getMethod().in // getMethod().in
} }
static void parseTagValue(TagList tagList, String nextTagComplete) { public boolean isReturnVoid() {
StringBuilder next = new StringBuilder(nextTagComplete); return myReturnVoid;
parseTagValue(tagList, nextTagComplete, next);
} }
/** private void addLocationHeader(Request theRequest, HttpServletResponse theResponse, MethodOutcome response) {
* @throws IOException StringBuilder b = new StringBuilder();
*/ b.append(theRequest.getFhirServerBase());
protected IResource parseIncomingServerResource(Request theRequest) throws IOException { b.append('/');
EncodingEnum encoding = RestfulServer.determineRequestEncoding(theRequest); b.append(getResourceName());
IParser parser = encoding.newParser(getContext()); b.append('/');
IResource resource = parser.parseResource(theRequest.getServletRequest().getReader()); b.append(response.getId().getIdPart());
return resource; 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 } * 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); protected abstract void addParametersForServerRequest(Request theRequest, Object[] theParams);
/** /**
@ -366,6 +274,16 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
*/ */
protected abstract String getMatchingOperation(); 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(); 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; 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.IOException;
import java.io.PushbackReader; import java.io.PushbackReader;
@ -79,6 +79,8 @@ import ca.uhn.fhir.util.ReflectionUtil;
*/ */
public class MethodUtil { 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); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
@ -132,7 +134,94 @@ public class MethodUtil {
String headerValue = clHeaders.get(0); String headerValue = clHeaders.get(0);
resource.getId().setValue(headerValue); 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) { static void addTagsToPostOrPut(IResource resource, BaseHttpClientInvocation retVal) {
TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST); TagList list = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);

View File

@ -20,11 +20,11 @@ package ca.uhn.fhir.rest.method;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
@ -72,7 +72,6 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
return RestfulOperationSystemEnum.TRANSACTION; return RestfulOperationSystemEnum.TRANSACTION;
} }
@Override @Override
public boolean incomingServerRequestMatchesMethod(Request theRequest) { public boolean incomingServerRequestMatchesMethod(Request theRequest) {
if (theRequest.getRequestType() != RequestType.POST) { if (theRequest.getRequestType() != RequestType.POST) {
@ -95,16 +94,24 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public IBundleProvider invokeServer(Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException { public IBundleProvider invokeServer(Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
List<IResource> resources = (List<IResource>) theMethodParams[myTransactionParamIndex]; // Grab the IDs of all of the resources in the transaction
List<IResource> resources;
List<IdDt> oldIds= new ArrayList<IdDt>(); if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
for (IResource next : resources) { resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
oldIds.add(next.getId()); } else {
resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
} }
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); Object response = invokeServerMethod(theMethodParams);
IBundleProvider retVal = toResourceList(response); IBundleProvider retVal = toResourceList(response);
/*
int offset = 0; int offset = 0;
if (retVal.size() != resources.size()) { if (retVal.size() != resources.size()) {
if (retVal.size() > 0 && retVal.getResources(0, 1).get(0) instanceof OperationOutcome) { if (retVal.size() > 0 && retVal.getResources(0, 1).get(0) instanceof OperationOutcome) {
@ -113,14 +120,17 @@ 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)"); 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()); List<IResource> retResources = retVal.getResources(0, retVal.size());
for (int i =0; i < resources.size(); i++) { for (int i = 0; i < retResources.size(); i++) {
IdDt oldId = oldIds.get(i); IdDt oldId = oldIds.get(retResources.get(i));
IResource newRes = retResources.get(i); IResource newRes = retResources.get(i);
if (newRes.getId() == null || newRes.getId().isEmpty()) { if (newRes.getId() == null || newRes.getId().isEmpty()) {
if (!(newRes instanceof OperationOutcome)) {
throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)"); throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)");
} }
}
if (oldId != null && !oldId.isEmpty()) { if (oldId != null && !oldId.isEmpty()) {
if (!oldId.equals(newRes.getId())) { if (!oldId.equals(newRes.getId())) {
@ -130,6 +140,9 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
} }
return retVal; return retVal;
} }
@Override @Override
@ -147,12 +160,16 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@Override @Override
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException { public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
FhirContext context = getContext();
if (theArgs[myTransactionParamIndex] instanceof Bundle) {
Bundle bundle = (Bundle) theArgs[myTransactionParamIndex];
return createTransactionInvocation(bundle, context);
} else {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex]; List<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex];
FhirContext context = getContext();
return createTransactionInvocation(resources, context); return createTransactionInvocation(resources, context);
} }
}
public static BaseHttpClientInvocation createTransactionInvocation(List<IResource> theResources, FhirContext theContext) { public static BaseHttpClientInvocation createTransactionInvocation(List<IResource> theResources, FhirContext theContext) {
return new HttpPostClientInvocation(theContext, theResources); return new HttpPostClientInvocation(theContext, theResources);

View File

@ -38,6 +38,8 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
class TransactionParamBinder implements IParameter { class TransactionParamBinder implements IParameter {
private boolean myParamIsBundle;
public TransactionParamBinder() { public TransactionParamBinder() {
} }
@ -50,6 +52,9 @@ class TransactionParamBinder implements IParameter {
@Override @Override
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException { public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
Bundle resource = (Bundle) theRequestContents; Bundle resource = (Bundle) theRequestContents;
if (myParamIsBundle) {
return resource;
}
ArrayList<IResource> retVal = new ArrayList<IResource>(); ArrayList<IResource> retVal = new ArrayList<IResource>();
for (BundleEntry next : resource.getEntries()) { for (BundleEntry next : resource.getEntries()) {
@ -66,11 +71,22 @@ class TransactionParamBinder implements IParameter {
if (theOuterCollectionType != null) { 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 (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) { 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()+">"); 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) { 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()+">"); 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; 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.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.server.Constants; 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_ACCEPT_ENCODING = "Accept-Encoding";
public static final String HEADER_AUTHORIZATION = "Authorization"; public static final String HEADER_AUTHORIZATION = "Authorization";
public static final String HEADER_CATEGORY = "Category"; 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_DISPOSITION = "Content-Disposition";
public static final String HEADER_CONTENT_ENCODING = "Content-Encoding"; public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
public static final String HEADER_CONTENT_LOCATION = "Content-Location"; 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_500_INTERNAL_ERROR = 500;
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501; public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
public static final String URL_TOKEN_HISTORY = "_history"; public static final String URL_TOKEN_HISTORY = "_history";
public static final String TAG_SCHEME_PROFILE = "http://hl7.org/fhir/tag/profile ";
static { static {
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>(); Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();

View File

@ -856,8 +856,8 @@ public class RestfulServer extends HttpServlet {
} while (references.isEmpty() == false); } while (references.isEmpty() == false);
BundleEntry entry = bundle.addResource(next, theContext, theServerBase); bundle.addResource(next, theContext, theServerBase);
addProfileToBundleEntry(theContext, next, entry); // addProfileToBundleEntry(theContext, next, entry);
} }
@ -865,24 +865,26 @@ public class RestfulServer extends HttpServlet {
* Actually add the resources to the bundle * Actually add the resources to the bundle
*/ */
for (IResource next : addedResources) { for (IResource next : addedResources) {
BundleEntry entry = bundle.addResource(next, theContext, theServerBase); bundle.addResource(next, theContext, theServerBase);
addProfileToBundleEntry(theContext, next, entry); // addProfileToBundleEntry(theContext, next, entry);
} }
bundle.getTotalResults().setValue(theTotalResults); bundle.getTotalResults().setValue(theTotalResults);
return bundle; return bundle;
} }
/*
private static void addProfileToBundleEntry(FhirContext theContext, IResource next, BundleEntry entry) { 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()) { if (profileTags.isEmpty()) {
RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(next); RuntimeResourceDefinition nextDef = theContext.getResourceDefinition(next);
String profile = nextDef.getResourceProfile(); String profile = nextDef.getResourceProfile();
if (isNotBlank(profile)) { 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) { public static String createPagingLink(String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();

View File

@ -1,7 +1,5 @@
package ca.uhn.fhir.rest.server.exceptions; package ca.uhn.fhir.rest.server.exceptions;
import java.text.ParseException;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
/* /*
@ -41,7 +39,7 @@ public class AuthenticationException extends BaseServerResponseException {
super(STATUS_CODE, theMessage); super(STATUS_CODE, theMessage);
} }
public AuthenticationException(String theMessage, ParseException theCause) { public AuthenticationException(String theMessage, Throwable theCause) {
super(STATUS_CODE, theMessage, 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 * Base class for RESTful client and server exceptions. RESTful client methods will only throw exceptions which are
* will only throw exceptions which are subclasses of this exception type, and * subclasses of this exception type, and RESTful server methods should also only call subclasses of this exception
* RESTful server methods should also only call subclasses of this exception
* type. * type.
*/ */
public abstract class BaseServerResponseException extends RuntimeException { public abstract class BaseServerResponseException extends RuntimeException {
@ -50,10 +49,8 @@ public abstract class BaseServerResponseException extends RuntimeException {
} }
private final OperationOutcome myOperationOutcome; private final OperationOutcome myOperationOutcome;
private String myResponseBody; private String myResponseBody;
private String myResponseMimeType; private String myResponseMimeType;
private int myStatusCode; private int myStatusCode;
/** /**
@ -77,6 +74,9 @@ public abstract class BaseServerResponseException extends RuntimeException {
* The HTTP status code corresponding to this problem * The HTTP status code corresponding to this problem
* @param theMessage * @param theMessage
* The message * 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) { public BaseServerResponseException(int theStatusCode, String theMessage, OperationOutcome theOperationOutcome) {
super(theMessage); super(theMessage);
@ -100,6 +100,25 @@ public abstract class BaseServerResponseException extends RuntimeException {
myOperationOutcome = null; 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 * Constructor
* *
@ -115,17 +134,32 @@ public abstract class BaseServerResponseException extends RuntimeException {
} }
/** /**
* Returns the {@link OperationOutcome} resource if any which was supplied * Constructor
* in the response, or <code>null</code> *
* @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() { public OperationOutcome getOperationOutcome() {
return myOperationOutcome; return myOperationOutcome;
} }
/** /**
* In a RESTful client, this method will be populated with the body of the * In a RESTful client, this method will be populated with the body of the HTTP respone if one was provided by the
* HTTP respone if one was provided by the server, or <code>null</code> * server, or <code>null</code> otherwise.
* otherwise.
* <p> * <p>
* In a restful server, this method is currently ignored. * In a restful server, this method is currently ignored.
* </p> * </p>
@ -135,8 +169,8 @@ public abstract class BaseServerResponseException extends RuntimeException {
} }
/** /**
* In a RESTful client, this method will be populated with the HTTP status * In a RESTful client, this method will be populated with the HTTP status code that was returned with the HTTP
* code that was returned with the HTTP response. * response.
* <p> * <p>
* In a restful server, this method is currently ignored. * In a restful server, this method is currently ignored.
* </p> * </p>
@ -153,16 +187,14 @@ public abstract class BaseServerResponseException extends RuntimeException {
} }
/** /**
* This method is currently only called internally by HAPI, it should not be * This method is currently only called internally by HAPI, it should not be called by user code.
* called by user code.
*/ */
public void setResponseBody(String theResponseBody) { public void setResponseBody(String theResponseBody) {
myResponseBody = theResponseBody; myResponseBody = theResponseBody;
} }
/** /**
* This method is currently only called internally by HAPI, it should not be * This method is currently only called internally by HAPI, it should not be called by user code.
* called by user code.
*/ */
public void setResponseMimeType(String theResponseMimeType) { public void setResponseMimeType(String theResponseMimeType) {
myResponseMimeType = 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.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions; import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.dstu.composite.ContainedDt; 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.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException; 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> * Visit all elements in a given resource
* and are either of the exact type specified, or are a subclass of that type. *
* <p> * @param theResource The resource to visit
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within * @param theVisitor The visitor
* 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.
* @return
*/ */
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, Class<T> theType) { public void visit(IResource theResource, IModelVisitor theVisitor) {
ArrayList<T> retVal = new ArrayList<T>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
getAllChildElementsOfType(theResource, def, theType, retVal); visit(theResource, null, def, theVisitor);
return retVal;
} }
private <T extends IElement> void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition<?> theDefinition, Class<T> theType, ArrayList<T> theList) { /**
* 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.
* </p>
*
* @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, final Class<T> theType) {
final ArrayList<T> retVal = new ArrayList<T>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
visit(theResource, null, def, new IModelVisitor() {
@SuppressWarnings("unchecked")
@Override
public void acceptElement(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
if (theElement.isEmpty()) { if (theElement.isEmpty()) {
return; return;
} }
addIfCorrectType(theElement, theType, theList); if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
addUndeclaredExtensions(theElement, theType, theList); 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 visit(IElement theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
theCallback.acceptElement(theElement, theChildDefinition, theDefinition);
addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
// if (theElement.isEmpty()) {
// return;
// }
switch (theDefinition.getChildType()) { switch (theDefinition.getChildType()) {
case PRIMITIVE_XHTML: case PRIMITIVE_XHTML:
@ -153,7 +192,9 @@ public class FhirTerser {
if (nextValue.isEmpty()) { if (nextValue.isEmpty()) {
continue; continue;
} }
BaseRuntimeElementDefinition<?> childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass()); BaseRuntimeElementDefinition<?> childElementDef;
childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
if (childElementDef == null) { if (childElementDef == null) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
b.append("Found value of type["); b.append("Found value of type[");
@ -171,7 +212,7 @@ public class FhirTerser {
} }
throw new DataFormatException(b.toString()); 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; ContainedDt value = (ContainedDt) theElement;
for (IResource next : value.getContainedResources()) { for (IResource next : value.getContainedResources()) {
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next);
getAllChildElementsOfType(next, def, theType, theList); visit(next, null, def, theCallback);
} }
break; 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) { if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions elem = (ISupportsUndeclaredExtensions) theElement; ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : elem.getUndeclaredExtensions()) { for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
addIfCorrectType(nextExt, theType, theList); theCallback.acceptUndeclaredExtension(containingElement, theChildDefinition, theDefinition, nextExt);
addIfCorrectType(nextExt.getValue(), theType, theList); addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
addUndeclaredExtensions(nextExt, theType, theList);
} }
} }
} }
@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="The Data Model" href="./doc_fhirobjects.html">
<item name="Extensions" href="./doc_extensions.html" /> <item name="Extensions" href="./doc_extensions.html" />
<item name="Resource References" href="./doc_resource_references.html" /> <item name="Resource References" href="./doc_resource_references.html" />
<item name="Tags" href="./doc_tags.html" />
</item> </item>
<item name="RESTful Client" href="./doc_rest_client.html" /> <item name="RESTful Client" href="./doc_rest_client.html" />
<item name="RESTful Server" href="./doc_rest_server.html" > <item name="RESTful Server" href="./doc_rest_server.html" >

View File

@ -28,7 +28,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="resourceExtension" /> <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> </macro>
<p> <p>
@ -36,7 +36,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="resourceStringExtension" /> <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> </macro>
<subsection name="Sub-Extensions"> <subsection name="Sub-Extensions">
@ -48,7 +48,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="subExtension" /> <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> </macro>
</subsection> </subsection>
@ -61,7 +61,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="parseExtension" /> <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> </macro>
</subsection> </subsection>
@ -78,7 +78,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="patientDef" /> <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> </macro>
<p> <p>
@ -88,7 +88,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="patientUse" /> <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> </macro>
<p> <p>
@ -121,7 +121,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="patientParse" /> <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> </macro>
<subsection name="Documentation"> <subsection name="Documentation">

View File

@ -31,7 +31,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="datatypes" /> <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> </macro>
<subsection name="Navigating Structures"> <subsection name="Navigating Structures">
@ -45,7 +45,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="nonNull" /> <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> </macro>
</subsection> </subsection>
@ -65,7 +65,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="codes" /> <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> </macro>
</subsection> </subsection>
@ -87,7 +87,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="namesHard" /> <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> </macro>
<p> <p>
@ -97,7 +97,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="namesEasy" /> <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> </macro>
</subsection> </subsection>

View File

@ -70,7 +70,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="creatingContext" /> <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> </macro>
</subsection> </subsection>
@ -93,7 +93,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="parseMsg" /> <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> </macro>
</subsection> </subsection>
@ -107,7 +107,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="encodeMsg" /> <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> </macro>
<!-- ****** The section below on fluent references the snippet above <!-- ****** The section below on fluent references the snippet above
@ -147,7 +147,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="encodeMsgFluent" /> <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> </macro>
</subsection> </subsection>
@ -160,7 +160,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="encodeMsgJson" /> <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> </macro>
<p> <p>

View File

@ -28,7 +28,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="simple" /> <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> </macro>
</section> </section>
@ -64,7 +64,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="example1" /> <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> </macro>
<p> <p>
@ -163,7 +163,7 @@ humanname.narrative=classpath:ca/uhn/fhir/narrative/HumanNameDt.html]]></source>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="gen" /> <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> </macro>
</section> </section>

View File

@ -27,8 +27,9 @@
There are two types of clients provided by HAPI: Generic and Annotation-driven. 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 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 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 client can rely on code generation and static binding to specific operations to
compile-time checking. give better compile-time checking against servers with a specific set of capabilities
exposed.
</p> </p>
</section> </section>
@ -47,7 +48,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="simple" /> <param name="id" value="simple" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<p> <p>
@ -76,27 +77,19 @@
</p> </p>
</subsection> </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"> <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> <p>
The following example shows how to query using the generic client: The following example shows how to query using the generic client:
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="search" /> <param name="id" value="search" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Multi-valued Parameters (ANY/OR)</h4> <h4>Search - Multi-valued Parameters (ANY/OR)</h4>
@ -108,7 +101,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchOr" /> <param name="id" value="searchOr" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Multi-valued Parameters (ALL/AND)</h4> <h4>Search - Multi-valued Parameters (ALL/AND)</h4>
@ -120,7 +113,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchOr" /> <param name="id" value="searchOr" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Paging</h4> <h4>Search - Paging</h4>
@ -131,7 +124,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchPaging" /> <param name="id" value="searchPaging" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Composite Parameters</h4> <h4>Search - Composite Parameters</h4>
@ -144,7 +137,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchComposite" /> <param name="id" value="searchComposite" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Other Query Options</h4> <h4>Search - Other Query Options</h4>
@ -155,7 +148,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchAdv" /> <param name="id" value="searchAdv" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
<h4>Search - Using HTTP POST or GET with _search</h4> <h4>Search - Using HTTP POST or GET with _search</h4>
@ -168,11 +161,23 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchPost" /> <param name="id" value="searchPost" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
</subsection> </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"> <subsection name="Instance - Delete">
<p> <p>
The following example shows how to perform a delete The following example shows how to perform a delete
@ -181,7 +186,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="delete" /> <param name="id" value="delete" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
</subsection> </subsection>
@ -198,7 +203,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="update" /> <param name="id" value="update" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
</subsection> </subsection>
@ -210,7 +215,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="conformance" /> <param name="id" value="conformance" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
</subsection> </subsection>
@ -221,7 +226,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="transaction" /> <param name="id" value="transaction" />
<param name="file" <param name="file"
value="src/site/example/java/example/GenericClientExample.java" /> value="examples/src/main/java/example/GenericClientExample.java" />
</macro> </macro>
</subsection> </subsection>
@ -295,7 +300,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="provider" /> <param name="id" value="provider" />
<param name="file" <param name="file"
value="src/site/example/java/example/IRestfulClient.java" /> value="examples/src/main/java/example/IRestfulClient.java" />
</macro> </macro>
<p> <p>
@ -321,7 +326,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="client" /> <param name="id" value="client" />
<param name="file" <param name="file"
value="src/site/example/java/example/ExampleRestfulClient.java" /> value="examples/src/main/java/example/ExampleRestfulClient.java" />
</macro> </macro>
</subsection> </subsection>
@ -343,7 +348,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="clientConfig" /> <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> </macro>
</subsection> </subsection>
@ -359,7 +364,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="client" /> <param name="id" value="client" />
<param name="file" <param name="file"
value="src/site/example/java/example/CompleteExampleClient.java" /> value="examples/src/main/java/example/CompleteExampleClient.java" />
</macro> </macro>
</subsection> </subsection>
@ -412,7 +417,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="security" /> <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> </macro>
</subsection> </subsection>
@ -429,7 +434,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="logging" /> <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> </macro>
</subsection> </subsection>
@ -443,7 +448,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="logging" /> <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> </macro>
</subsection> </subsection>

View File

@ -202,7 +202,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="read" /> <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> </macro>
<p> <p>
@ -218,7 +218,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="clientReadInterface" /> <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> </macro>
<a name="instance_vread" /> <a name="instance_vread" />
@ -243,7 +243,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="vread" /> <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> </macro>
<p> <p>
@ -294,7 +294,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="update" /> <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> </macro>
<p> <p>
@ -311,7 +311,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="updateClient" /> <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> </macro>
<a name="instance_delete" /> <a name="instance_delete" />
@ -336,7 +336,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="delete" /> <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> </macro>
<p> <p>
@ -407,7 +407,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="create" /> <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> </macro>
<p> <p>
@ -424,7 +424,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="createClient" /> <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> </macro>
<a name="type_search" /> <a name="type_search" />
@ -456,7 +456,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchAll" /> <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> </macro>
<p> <p>
@ -495,7 +495,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchStringParam" /> <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> </macro>
<p> <p>
@ -517,7 +517,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchIdentifierParam" /> <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> </macro>
<p> <p>
@ -550,7 +550,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="dates" /> <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> </macro>
<p> <p>
@ -565,7 +565,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="dateClient" /> <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> </macro>
</subsection> </subsection>
@ -597,7 +597,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="dateRange" /> <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> </macro>
<p> <p>
@ -612,7 +612,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="dateClient" /> <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> </macro>
<h4>Unbounded Ranges</h4> <h4>Unbounded Ranges</h4>
@ -658,7 +658,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="quantity" /> <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> </macro>
<p> <p>
@ -699,7 +699,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="reference" /> <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> </macro>
<p> <p>
@ -722,7 +722,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="referenceChain" /> <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> </macro>
</subsection> </subsection>
@ -744,7 +744,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchComposite" /> <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> </macro>
<p> <p>
@ -800,7 +800,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchOptionalParam" /> <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> </macro>
<p> <p>
@ -878,7 +878,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchMultiple" /> <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> </macro>
<p> <p>
@ -910,7 +910,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchMultipleAnd" /> <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> </macro>
<h4>AND Relationship Query Parameters for Dates</h4> <h4>AND Relationship Query Parameters for Dates</h4>
@ -940,7 +940,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="pathSpec" /> <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> </macro>
<p> <p>
@ -957,7 +957,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="pathSpecSimple" /> <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> </macro>
</subsection> </subsection>
@ -979,7 +979,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchNamedQuery" /> <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> </macro>
<p> <p>
@ -1016,7 +1016,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="sort" /> <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> </macro>
<p> <p>
@ -1041,7 +1041,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="searchWithDocs" /> <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> </macro>
</subsection> </subsection>
@ -1108,7 +1108,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="validate" /> <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> </macro>
<p> <p>
@ -1150,7 +1150,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="metadataProvider" /> <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> </macro>
<p> <p>
@ -1160,7 +1160,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="metadataClient" /> <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> </macro>
<p> <p>
@ -1171,7 +1171,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="metadataClientUsage" /> <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> </macro>
<a name="system_transaction" /> <a name="system_transaction" />
@ -1198,9 +1198,14 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="transaction" /> <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> </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> <p>
Example URL to invoke this method: Example URL to invoke this method:
<br /> <br />
@ -1315,7 +1320,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="history" /> <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> </macro>
<p> <p>
@ -1324,7 +1329,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="historyClient" /> <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> </macro>
<a name="exceptions" /> <a name="exceptions" />
@ -1406,7 +1411,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="readTags" /> <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> </macro>
<p> <p>
@ -1417,7 +1422,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="clientReadTags" /> <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> </macro>
</subsection> </subsection>
@ -1444,7 +1449,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="createTags" /> <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> </macro>
</subsection> </subsection>
@ -1464,7 +1469,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="tagMethodProvider" /> <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> </macro>
<p> <p>

View File

@ -57,7 +57,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="provider" /> <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> </macro>
</subsection> </subsection>
@ -88,7 +88,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="servlet" /> <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> </macro>
<a name="plain_providers"/> <a name="plain_providers"/>
@ -120,7 +120,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="plainProvider" /> <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> </macro>
<p> <p>
@ -136,7 +136,7 @@
</p> </p>
<macro name="snippet"> <macro name="snippet">
<param name="id" value="plainProviderServer" /> <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> </macro>
</subsection> </subsection>
@ -258,7 +258,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="provider" /> <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> </macro>
</subsection> </subsection>
@ -290,7 +290,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="provider" /> <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> </macro>
</subsection> </subsection>
@ -323,7 +323,7 @@
<macro name="snippet"> <macro name="snippet">
<param name="id" value="underlyingReq" /> <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> </macro>
@ -435,6 +435,41 @@
</section> </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"> <section name="A Complete Example">
<p> <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); MyPatient parsed = ourCtx.newXmlParser().parseResource(MyPatient.class, str);
assertEquals("foo", parsed.getIdentifierFirstRep().getSystem().getValueAsString()); 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 org.junit.Test;
import ca.uhn.fhir.model.dstu.resource.CarePlan; 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.DataFormatException;
import ca.uhn.fhir.parser.MyPatient;
public class ModelScannerTest { public class ModelScannerTest {
@ -15,6 +17,16 @@ public class ModelScannerTest {
new ModelScanner(CarePlan.class); 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 @Test
public void testScanExtensionTypes() throws DataFormatException { public void testScanExtensionTypes() throws DataFormatException {

View File

@ -363,6 +363,29 @@ public class JsonParserTest {
@Test @Test
public void testEncodeBundleCategory() { 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(); Bundle b = new Bundle();
BundleEntry e = b.addEntry(); BundleEntry e = b.addEntry();
e.setResource(new Patient()); e.setResource(new Patient());
@ -383,7 +406,6 @@ public class JsonParserTest {
} }
@Test @Test
public void testEncodeContainedResources() throws IOException { public void testEncodeContainedResources() throws IOException {
@ -542,7 +564,7 @@ public class JsonParserTest {
patient.setManagingOrganization(new ResourceReferenceDt("Organization/123")); patient.setManagingOrganization(new ResourceReferenceDt("Organization/123"));
str = p.encodeResourceToString(patient); str = p.encodeResourceToString(patient);
assertThat(str, StringContains.containsString("\"managingOrganization\":{\"resource\":\"Organization/123\"}")); assertThat(str, StringContains.containsString("\"managingOrganization\":{\"reference\":\"Organization/123\"}"));
Organization org = new Organization(); Organization org = new Organization();
org.addIdentifier().setSystem("foo").setValue("bar"); org.addIdentifier().setSystem("foo").setValue("bar");
@ -671,6 +693,11 @@ public class JsonParserTest {
IParser p = ourCtx.newJsonParser(); IParser p = ourCtx.newJsonParser();
Bundle bundle = p.parseBundle(msg); 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); String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
ourLog.info(encoded); 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.api.annotation.ResourceDef;
import ca.uhn.fhir.model.dstu.resource.Organization; import ca.uhn.fhir.model.dstu.resource.Organization;
@ResourceDef(name="Organization") @ResourceDef()
public class MyOrganization extends Organization { 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.DateTimeDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
@ResourceDef(name="Patient") @ResourceDef()
public class MyPatient extends Patient { public class MyPatient extends Patient {
@Child(name="petName") @Child(name="petName")

View File

@ -63,16 +63,19 @@ import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
public class XmlParserTest { public class XmlParserTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
private static FhirContext ourCtx; private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
@Test @Test
public void testParseLanguage() { public void testEncodeBinaryResource() {
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); 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 @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 @Test
public void testEncodeBundle() throws InterruptedException { public void testEncodeBundle() throws InterruptedException {
Bundle b= new Bundle(); Bundle b= new Bundle();
b.getCategories().addTag("http://hl7.org/fhir/tag", "http://hl7.org/fhir/tag/message", "Message");
InstantDt pub = InstantDt.withCurrentTime(); InstantDt pub = InstantDt.withCurrentTime();
b.setPublished(pub); b.setPublished(pub);
@ -393,6 +123,7 @@ public class XmlParserTest {
List<String> strings = new ArrayList<String>(); List<String> strings = new ArrayList<String>();
strings.addAll(Arrays.asList("<published>", pub.getValueAsString(), "</published>")); 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>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("<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", "/>")); 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 @Test
public void testEncodeContainedAndIncludedResources() { public void testEncodeContainedAndIncludedResources() {
@ -421,8 +190,6 @@ public class XmlParserTest {
} }
@Test @Test
public void testEncodeContainedResources() { 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 @Test
public void testEncodeInvalidChildGoodException() { public void testEncodeInvalidChildGoodException() {
Observation obs = new Observation(); 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 @Test
public void testEncodeResourceRef() throws DataFormatException { 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 @Test
public void testExtensions() throws DataFormatException { public void testExtensions() throws DataFormatException {
@ -630,6 +540,7 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical()); assertTrue(d.toString(), d.identical());
} }
@Test @Test
public void testLoadAndEncodeUndeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException { public void testLoadAndEncodeUndeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException {
IParser p = ourCtx.newXmlParser(); IParser p = ourCtx.newXmlParser();
@ -683,25 +594,6 @@ public class XmlParserTest {
assertTrue(d.toString(), d.identical()); 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 @Test
public void testLoadObservation() throws ConfigurationException, DataFormatException, IOException { 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 @Test
public void testNarrativeGeneration() throws DataFormatException { public void testNarrativeGeneration() throws DataFormatException {
@ -791,12 +729,50 @@ public class XmlParserTest {
} }
@Test @Test
public void testParseBundleWithMixedReturnTypes() { public void testNestedContainedResources() {
InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str); Observation A = new Observation();
assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass()); A.getName().setText("A");
assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass());
assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass()); 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") @SuppressWarnings("deprecation")
@ -814,6 +790,7 @@ public class XmlParserTest {
" <title>FHIR Core Valuesets</title>\n" + " <title>FHIR Core Valuesets</title>\n" +
" <id>http://hl7.org/fhir/profile/valuesets</id>\n" + " <id>http://hl7.org/fhir/profile/valuesets</id>\n" +
" <link href=\"http://hl7.org/implement/standards/fhir/valuesets.xml\" rel=\"self\"/>\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" + " <updated>2014-02-10T04:11:24.435-00:00</updated>\n" +
" <entry>\n" + " <entry>\n" +
" <title>Valueset &quot;256a5231-a2bb-49bd-9fea-f349d428b70d&quot; to support automated processing</title>\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(); IParser p = new FhirContext(ValueSet.class).newXmlParser();
Bundle bundle = p.parseBundle(msg); 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("FHIR Core Valuesets", bundle.getTitle().getValue());
assertEquals("http://hl7.org/implement/standards/fhir/valuesets.xml", bundle.getLinkSelf().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()); assertEquals("2014-02-10T04:11:24.435+00:00", bundle.getUpdated().getValueAsString());
@ -946,7 +926,6 @@ public class XmlParserTest {
} }
@Test @Test
public void testParseBundleLarge() throws IOException { 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 @Test
public void testParseContainedResources() throws IOException { 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 @Test
public void testParseEncodeNarrative() { public void testParseEncodeNarrative() {
@ -1010,103 +985,66 @@ public class XmlParserTest {
} }
@BeforeClass /**
public static void beforeClass() { * This sample has extra elements in <searchParam> that are not actually a
XMLUnit.setIgnoreAttributeOrder(true); * part of the spec any more..
XMLUnit.setIgnoreComments(true); */
XMLUnit.setIgnoreWhitespace(true); @Test
ourCtx = new FhirContext(); 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 @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(); assertEquals("zh-CN", pt.getLanguage().getValue());
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 @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(); assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString());
assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString());
HumanNameDt name = patient.addName(); assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString());
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 @Test
public void testExtensionOnPrimitive() throws Exception { public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
IParser p = ourCtx.newXmlParser();
Patient patient = new Patient(); //@formatter:off
String msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
HumanNameDt name = patient.addName(); "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
StringDt family = name.addFamily(); " <identifier>\n" +
family.setValue("Shmoe"); " <label value=\"IdentifierLabel\"/>\n" +
" </identifier>\n" +
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello")); "</Patient>";
family.addUndeclaredExtension(ext2); //@formatter:on
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());
Patient resource = (Patient) p.parseResource(msg);
assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue());
} }
@Test @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; package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -581,9 +579,11 @@ public class ClientTest {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class); ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(httpClient.execute(capt.capture())).thenReturn(httpResponse); when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
Header[] headers = new Header[2]; Header[] headers = new Header[] {
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"); 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"); 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.getAllHeaders()).thenReturn(headers);
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); 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); lm.setTimeZoneZulu(true);
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString()); 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 @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.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().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"))); when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
Header[] headers = new Header[2]; Header[] headers = new Header[] {
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"); 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"); 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); when(myHttpResponse.getAllHeaders()).thenReturn(headers);
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir"); IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
@ -289,6 +291,13 @@ public class GenericClientTest {
lm.setTimeZoneZulu(true); lm.setTimeZoneZulu(true);
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString()); 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") @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().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"))); 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()); assertEquals(HttpPost.class, capt.getValue().getClass());
HttpPost post = (HttpPost) capt.getValue(); HttpPost post = (HttpPost) capt.getValue();
@ -92,6 +92,47 @@ public class TransactionClientTest {
assertTrue(bundle.getEntries().get(1).getId().isEmpty()); 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 static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionClientTest.class);
private String createBundle() { private String createBundle() {
return ctx.newXmlParser().encodeBundleToString(new Bundle()); return ctx.newXmlParser().encodeBundleToString(new Bundle());
@ -100,7 +141,15 @@ public class TransactionClientTest {
private interface IClient extends IBasicClient { private interface IClient extends IBasicClient {
@Transaction @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\""; 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(); TagList parsedFromHeader = new TagList();
BaseOutcomeReturningMethodBinding.parseTagValue(parsedFromHeader, headerString); MethodUtil.parseTagValue(parsedFromHeader, headerString);
//@formatter:off //@formatter:off
String resourceString = "{\n" + String resourceString = "{\n" +

View File

@ -63,7 +63,7 @@ public class CustomTypeTest {
assertEquals(1, bundle.getEntries().size()); assertEquals(1, bundle.getEntries().size());
BundleEntry entry = bundle.getEntries().get(0); 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(1, profileTags.size());
assertEquals("http://foo/profiles/Profile", profileTags.get(0).getTerm()); 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.HttpResponse;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity; 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.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient; 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.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource; 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.composite.CodingDt;
import ca.uhn.fhir.model.dstu.resource.Observation; import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Patient; 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.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.annotation.OptionalParam; import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RequiredParam; import ca.uhn.fhir.rest.annotation.RequiredParam;
@ -149,6 +152,29 @@ public class SearchTest {
assertEquals("AAANamed", p.getIdentifierFirstRep().getValue().getValue()); 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 @AfterClass
public static void afterClass() throws Exception { public static void afterClass() throws Exception {
ourServer.stop(); ourServer.stop();
@ -206,7 +232,7 @@ public class SearchTest {
public static class DummyPatientResourceProvider implements IResourceProvider { public static class DummyPatientResourceProvider implements IResourceProvider {
@Search @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>(); ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient patient = new Patient(); Patient patient = new Patient();
@ -220,7 +246,7 @@ public class SearchTest {
} }
@Search @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>(); ArrayList<Patient> retVal = new ArrayList<Patient>();
Patient patient = new Patient(); Patient patient = new Patient();
@ -241,6 +267,19 @@ public class SearchTest {
return retVal; 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 @Override
public Class<? extends IResource> getResourceType() { public Class<? extends IResource> getResourceType() {
return Patient.class; return Patient.class;

View File

@ -41,17 +41,16 @@ public class TransactionTest {
private static CloseableHttpClient ourClient; private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = new FhirContext(); 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 final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionTest.class);
private static int ourPort; private static int ourPort;
private static boolean ourReturnOperationOutcome; private static boolean ourReturnOperationOutcome;
private static Server ourServer; private static Server ourServer;
@Before @Before
public void before() { public void before() {
ourReturnOperationOutcome = false; ourReturnOperationOutcome = false;
ourDropFirstResource = false;
} }
@Test @Test
@ -82,7 +81,8 @@ public class TransactionTest {
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true"); httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8"))); httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost); 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()); assertEquals(200, status.getStatusLine().getStatusCode());
@ -107,6 +107,56 @@ public class TransactionTest {
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString()); 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 @Test
public void testTransactionWithOperationOutcome() throws Exception { public void testTransactionWithOperationOutcome() throws Exception {
@ -138,7 +188,8 @@ public class TransactionTest {
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true"); httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8"))); httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost); 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()); assertEquals(200, status.getStatusLine().getStatusCode());
@ -214,19 +265,21 @@ public class TransactionTest {
index++; index++;
} }
List<IResource> retVal = theResources; List<IResource> retVal = new ArrayList<IResource>(theResources);
if (ourDropFirstResource) {
retVal.remove(0);
}
if (ourReturnOperationOutcome) { if (ourReturnOperationOutcome) {
retVal = new ArrayList<IResource>();
OperationOutcome oo = new OperationOutcome(); OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDetails("AAAAA"); oo.addIssue().setDetails("AAAAA");
retVal.add(oo); retVal.add(0, oo);
retVal.addAll(theResources);
} }
return retVal; 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", "updated" : "2014-03-22T15:37:12Z",
"category" : [{
"term" : "http://term",
"label" : "label",
"scheme" : "http://scheme"
}],
"totalResults" : "356", "totalResults" : "356",
"entry" : [ "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"> <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> <dependency-type>uses</dependency-type>
</dependent-module> </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> <dependency-type>consumes</dependency-type>
</dependent-module> </dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&amp;excludes=META-INF/MANIFEST.MF"> <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..."); ourLog.info("Loading profiles...");
ProfileParser pp = new ProfileParser(); ProfileParser pp = new ProfileParser();
for (ProfileFileDefinition next : resourceProfileFiles) { for (ProfileFileDefinition next : resourceProfileFiles) {
ourLog.info("Parsing file: {}", next.profileFile);
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl); 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 { 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(); ValueSetGenerator vsp = new ValueSetGenerator();
// vsp.setDirectory("src/test/resources/vs/"); // vsp.setDirectory("src/test/resources/vs/");
vsp.parse(); vsp.parse();
@ -194,8 +199,9 @@ public class TinderStructuresMojo extends AbstractMojo {
dtp.writeAll(new File(dtOutputDir), "ca.uhn.fhir.model.dstu"); dtp.writeAll(new File(dtOutputDir), "ca.uhn.fhir.model.dstu");
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet(); ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
rp.setBaseResourceNames(Arrays.asList("observation")); rp.setBaseResourceNames(Arrays.asList("patient"));
rp.parse(); rp.parse();
// rp.bindValueSets(vsp); // rp.bindValueSets(vsp);
String rpOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/resource"; String rpOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/resource";

View File

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