CCHIT-xds-facade 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/apache-mime4j-0.5.jar +0 -0
- data/lib/commons-codec-1.3.jar +0 -0
- data/lib/commons-httpclient-3.1.jar +0 -0
- data/lib/commons-logging-1.1.1.jar +0 -0
- data/lib/mime/mime_message_parser.rb +52 -0
- data/lib/xds-facade.rb +77 -0
- data/lib/xds/affinity_domain_config.rb +42 -0
- data/lib/xds/author.rb +33 -0
- data/lib/xds/coded_attribute.rb +44 -0
- data/lib/xds/document_registry_service.rb +26 -0
- data/lib/xds/document_repository_service.rb +27 -0
- data/lib/xds/helper.rb +81 -0
- data/lib/xds/metadata.rb +179 -0
- data/lib/xds/mtom_xop_request.rb +29 -0
- data/lib/xds/provide_and_register_document_set_b.rb +29 -0
- data/lib/xds/provide_and_register_document_set_b_xop.rb +58 -0
- data/lib/xds/provide_and_register_document_set_b_xop_response.rb +45 -0
- data/lib/xds/registry_stored_query_request.rb +38 -0
- data/lib/xds/registry_stored_query_response.rb +31 -0
- data/lib/xds/retrieve_document_set_request.rb +66 -0
- data/lib/xds/retrieve_document_set_response.rb +41 -0
- data/lib/xds/source_patient_info.rb +52 -0
- data/lib/xds/xds_header.rb +26 -0
- data/lib/xds/xds_part.rb +44 -0
- data/lib/xds/xds_request.rb +55 -0
- data/lib/xds/xds_request_entity.rb +14 -0
- data/test/factories.rb +37 -0
- data/test/mime/mime_message_parser_test.rb +25 -0
- data/test/test_helper.rb +39 -0
- data/test/xds/affinity_domain_config_test.rb +26 -0
- data/test/xds/author_test.rb +30 -0
- data/test/xds/coded_attribute_test.rb +38 -0
- data/test/xds/metadata_test.rb +60 -0
- data/test/xds/provide_and_register_document_set_b_test.rb +31 -0
- data/test/xds/registry_stored_query_request_test.rb +32 -0
- data/test/xds/registry_stored_query_response_test.rb +28 -0
- data/test/xds/retrieve_document_set_request_test.rb +32 -0
- data/test/xds/retrieve_document_set_response_test.rb +43 -0
- data/test/xds/source_patient_info_test.rb +59 -0
- data/test/xds/xds_header.rb +20 -0
- data/test/xds/xml_helper_test.rb +124 -0
- metadata +122 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module MIME
|
|
2
|
+
# The constructor for MimeTokenStream that takes a MimeEntityConfig is
|
|
3
|
+
# protected. We need to pass in a new config becuse the default one
|
|
4
|
+
# has a max line length of 1000. Since we will be getting SOAP repsonses
|
|
5
|
+
# with out new lines, we will easily exceed that. This class produces
|
|
6
|
+
# a MimeTokenStream with a longer max line length
|
|
7
|
+
class FixedMimeTokenStream < org.apache.james.mime4j.parser.MimeTokenStream
|
|
8
|
+
def initialize()
|
|
9
|
+
config = MimeEntityConfig.new
|
|
10
|
+
config.max_line_len = 4096
|
|
11
|
+
super(config)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class MimeMessageParser
|
|
16
|
+
|
|
17
|
+
# Parses a mime message and returns an array of hashes for each part of the message
|
|
18
|
+
# The hash will contain the following:
|
|
19
|
+
# * <tt>:content_type</tt> - The content type of the message part
|
|
20
|
+
# * <tt>:content_id</tt> - The id of the content (useful for dealing with MTOM/XOP)
|
|
21
|
+
# * <tt>:content</tt> - The actual content of the message as a String
|
|
22
|
+
def self.parse(input_stream, content_type)
|
|
23
|
+
parts = []
|
|
24
|
+
mts = FixedMimeTokenStream.new()
|
|
25
|
+
mts.parse_headless(input_stream, content_type)
|
|
26
|
+
current_message = {}
|
|
27
|
+
until(mts.state == MimeTokenStream::T_END_OF_STREAM)
|
|
28
|
+
case mts.state
|
|
29
|
+
when MimeTokenStream::T_FIELD
|
|
30
|
+
if mts.field_name.eql?('Content-Type')
|
|
31
|
+
current_message[:content_type] = mts.field_value.strip
|
|
32
|
+
end
|
|
33
|
+
if mts.field_name.eql?('Content-ID')
|
|
34
|
+
current_message[:content_id] = mts.field_value.strip
|
|
35
|
+
end
|
|
36
|
+
when MimeTokenStream::T_BODY
|
|
37
|
+
reader = java.io.LineNumberReader.new(mts.reader)
|
|
38
|
+
content = ''
|
|
39
|
+
while (line = reader.readLine)
|
|
40
|
+
content << line
|
|
41
|
+
content << "\n"
|
|
42
|
+
end
|
|
43
|
+
current_message[:content] = content
|
|
44
|
+
parts << current_message
|
|
45
|
+
current_message = {}
|
|
46
|
+
end
|
|
47
|
+
mts.next
|
|
48
|
+
end
|
|
49
|
+
parts
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/xds-facade.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
if RUBY_PLATFORM =~ /java/
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'builder'
|
|
4
|
+
require 'uuid'
|
|
5
|
+
require 'java'
|
|
6
|
+
require 'activesupport'
|
|
7
|
+
require 'rexml/document'
|
|
8
|
+
|
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + '/commons-codec-1.3.jar')
|
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/commons-logging-1.1.1.jar')
|
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/commons-httpclient-3.1.jar')
|
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/apache-mime4j-0.5.jar')
|
|
13
|
+
|
|
14
|
+
import "org.apache.commons.httpclient.HttpClient"
|
|
15
|
+
import "org.apache.commons.httpclient.methods.PostMethod"
|
|
16
|
+
import "org.apache.commons.httpclient.methods.StringRequestEntity"
|
|
17
|
+
import "org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity"
|
|
18
|
+
import "org.apache.commons.httpclient.methods.multipart.Part"
|
|
19
|
+
import "org.apache.commons.httpclient.methods.multipart.StringPart"
|
|
20
|
+
import "org.apache.commons.httpclient.methods.multipart.FilePart"
|
|
21
|
+
import "org.apache.james.mime4j.parser.MimeTokenStream"
|
|
22
|
+
import "org.apache.james.mime4j.parser.MimeEntityConfig"
|
|
23
|
+
import "org.apache.commons.httpclient.util.EncodingUtil"
|
|
24
|
+
|
|
25
|
+
require File.expand_path(File.dirname(__FILE__) + '/mime/mime_message_parser')
|
|
26
|
+
|
|
27
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/helper')
|
|
28
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/xds_header')
|
|
29
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/xds_request')
|
|
30
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/mtom_xop_request')
|
|
31
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/author')
|
|
32
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/coded_attribute')
|
|
33
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/metadata')
|
|
34
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/source_patient_info')
|
|
35
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/xds_part')
|
|
36
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/xds_request_entity')
|
|
37
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/provide_and_register_document_set_b')
|
|
38
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/provide_and_register_document_set_b_xop')
|
|
39
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/provide_and_register_document_set_b_xop_response')
|
|
40
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/retrieve_document_set_request')
|
|
41
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/retrieve_document_set_response')
|
|
42
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/registry_stored_query_request')
|
|
43
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/registry_stored_query_response')
|
|
44
|
+
require File.expand_path(File.dirname(__FILE__) + '/xds/affinity_domain_config')
|
|
45
|
+
|
|
46
|
+
else
|
|
47
|
+
warn "xds-facade is only for use with JRuby"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module XDS
|
|
51
|
+
COMMON_NAMESPACES = {'xdsb' => "urn:ihe:iti:xds-b:2007",
|
|
52
|
+
'soapenv' =>"http://www.w3.org/2003/05/soap-envelope",
|
|
53
|
+
'wsa' => "http://www.w3.org/2005/08/addressing",
|
|
54
|
+
'rs' => "urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0",
|
|
55
|
+
'xop' => "http://www.w3.org/2004/08/xop/include",
|
|
56
|
+
'query' => "urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0",
|
|
57
|
+
'rim' => 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0'}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
PROXY_CONFIG = begin
|
|
61
|
+
proxy_config = {}
|
|
62
|
+
host = ENV['xds_proxy'] || ENV['http_proxy']
|
|
63
|
+
if host
|
|
64
|
+
host.try(:gsub!, "http://", "")
|
|
65
|
+
host.try(:gsub!, "https://", "")
|
|
66
|
+
end
|
|
67
|
+
if host
|
|
68
|
+
host = host.split(":")
|
|
69
|
+
proxy_config = {:host=>host[0],:port=>(host.length>1)?host[1].to_i : 80}
|
|
70
|
+
end
|
|
71
|
+
proxy_config
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.proxy_config
|
|
75
|
+
XDS::PROXY_CONFIG
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module XDS
|
|
2
|
+
class AffinityDomainConfig
|
|
3
|
+
CODE_TYPE_NAME_TO_CODED_ATTRIBUTE = {
|
|
4
|
+
'classCode' => :class_code,
|
|
5
|
+
'confidentialityCode' => :confidentiality_code,
|
|
6
|
+
'formatCode' => :format_code,
|
|
7
|
+
'healthcareFacilityTypeCode' => :healthcare_facility_type_code,
|
|
8
|
+
'practiceSettingCode' => :practice_setting_code,
|
|
9
|
+
'typeCode' => :type_code
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def initialize(config_file)
|
|
13
|
+
config_doc = REXML::Document.new(File.new(config_file, 'r'))
|
|
14
|
+
@code_types = {}
|
|
15
|
+
config_doc.root.elements.each('CodeType') do |code_type|
|
|
16
|
+
code_type_name = code_type.attributes['name']
|
|
17
|
+
if CODE_TYPE_NAME_TO_CODED_ATTRIBUTE[code_type_name]
|
|
18
|
+
attribute_type = CODE_TYPE_NAME_TO_CODED_ATTRIBUTE[code_type_name]
|
|
19
|
+
@code_types[attribute_type] = [] unless @code_types[attribute_type]
|
|
20
|
+
code_type.elements.each('Code') do |code|
|
|
21
|
+
code_value = code.attributes['code']
|
|
22
|
+
display_name = code.attributes['display']
|
|
23
|
+
coding_scheme = code.attributes['codingScheme']
|
|
24
|
+
@code_types[attribute_type] << CodedAttribute.new(attribute_type, code_value, display_name, coding_scheme)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def coded_attribute(attribute_type, code)
|
|
31
|
+
if @code_types[attribute_type]
|
|
32
|
+
@code_types[attribute_type].find() {|ca| ca.code.eql?(code)}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def select_options(attribute_type)
|
|
37
|
+
if @code_types[attribute_type]
|
|
38
|
+
@code_types[attribute_type].map {|ca| [ca.display_name, ca.code]}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/xds/author.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module XDS
|
|
2
|
+
class Author
|
|
3
|
+
include XDS::Helper
|
|
4
|
+
CLASSIFICATION_SCHEME = 'urn:uuid:93606bcf-9494-43ec-9b4e-a7748d1a838d'
|
|
5
|
+
|
|
6
|
+
attr_accessor :institution, :person, :role, :specialty
|
|
7
|
+
|
|
8
|
+
def initialize(institution="",person="", role="",specialty="")
|
|
9
|
+
@institution = institution
|
|
10
|
+
@person = person
|
|
11
|
+
@role=role
|
|
12
|
+
@specialty=specialty
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_soap(builder, object_id)
|
|
16
|
+
create_classification(builder,CLASSIFICATION_SCHEME,object_id,"") do |build|
|
|
17
|
+
create_slot(builder,'authorInstitution', [@institution])
|
|
18
|
+
create_slot(builder,'authorPerson', @person)
|
|
19
|
+
create_slot(builder,'authorRole', @role)
|
|
20
|
+
create_slot(builder,'authorSpecialty', @specialty)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def from_extrinsic_object(eo_node)
|
|
25
|
+
with_classification(eo_node, CLASSIFICATION_SCHEME) do |classification|
|
|
26
|
+
@institution = get_slot_value(classification, 'authorInstitution')
|
|
27
|
+
@person = get_slot_value(classification, 'authorPerson')
|
|
28
|
+
@role = get_slot_value(classification, 'authorRole')
|
|
29
|
+
@specialty = get_slot_value(classification, 'authorSpecialty')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module XDS
|
|
2
|
+
class CodedAttribute
|
|
3
|
+
include XDS::Helper
|
|
4
|
+
attr_reader :classification_scheme, :code, :display_name, :coding_scheme
|
|
5
|
+
|
|
6
|
+
def initialize(attribute_type, code = nil, display_name = nil, coding_scheme = nil)
|
|
7
|
+
case attribute_type
|
|
8
|
+
when :class_code
|
|
9
|
+
@classification_scheme = 'urn:uuid:41a5887f-8865-4c09-adf7-e362475b143a'
|
|
10
|
+
when :confidentiality_code
|
|
11
|
+
@classification_scheme = 'urn:uuid:f4f85eac-e6cb-4883-b524-f2705394840f'
|
|
12
|
+
when :format_code
|
|
13
|
+
@classification_scheme = 'urn:uuid:a09d5840-386c-46f2-b5ad-9c3699a4309d'
|
|
14
|
+
when :healthcare_facility_type_code
|
|
15
|
+
@classification_scheme = 'urn:uuid:f33fb8ac-18af-42cc-ae0e-ed0b0bdb91e1'
|
|
16
|
+
when :practice_setting_code
|
|
17
|
+
@classification_scheme = 'urn:uuid:cccf5598-8b07-4b77-a05e-ae952c785ead'
|
|
18
|
+
when :type_code
|
|
19
|
+
@classification_scheme = 'urn:uuid:f0306f51-975f-434e-a61c-c59651d33983'
|
|
20
|
+
end
|
|
21
|
+
@code = code
|
|
22
|
+
@display_name = display_name
|
|
23
|
+
@coding_scheme=coding_scheme
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_soap(builder, object_id)
|
|
27
|
+
create_classification(builder,@classification_scheme,object_id,@code) do |build|
|
|
28
|
+
create_slot(build,"codingScheme",@coding_scheme || [])
|
|
29
|
+
create_name(build,@display_name)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def from_extrinsic_object(eo_node)
|
|
34
|
+
with_classification(eo_node, @classification_scheme) do |classification|
|
|
35
|
+
@code = classification.attributes['nodeRepresentation']
|
|
36
|
+
localized_string_node = REXML::XPath.first(classification, 'rim:Name/rim:LocalizedString')
|
|
37
|
+
if localized_string_node
|
|
38
|
+
@display_name = localized_string_node.attributes['value']
|
|
39
|
+
end
|
|
40
|
+
@coding_scheme = get_slot_value(classification, 'codingScheme')
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Provides an interface to an XDS Document Registry
|
|
2
|
+
class DocumentRegistry
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def initialize(service_url)
|
|
6
|
+
@service_url = service_url
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def register_document_set_b
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Issues a stored query request to the XDS Document Registry
|
|
14
|
+
# Will return an Array of XDS::Metadata
|
|
15
|
+
# <tt>query</tt> - a Hash where the key is the parameter name and value is the value to query against
|
|
16
|
+
# call-seq:
|
|
17
|
+
# dr = DocumentRegistry.new(http://yourregistry.com/xdsb)
|
|
18
|
+
# dr.registery_stored_query({"$XDSDocumentEntryPatientId" => "'93f3f8a6d100463^^^&1.3.6.1.4.1.21367.2005.3.7&ISO'",
|
|
19
|
+
# "$XDSDocumentEntryStatus" => "('urn:oasis:names:tc:ebxml-regrep:StatusType:Approved')"})
|
|
20
|
+
def registery_stored_query(query)
|
|
21
|
+
rsqr = XDS::RegistryStoredQueryRequest.new(@service_url, query)
|
|
22
|
+
rsqr.retrieved_metadata
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class DocumentRepositoryService
|
|
2
|
+
|
|
3
|
+
def initialize(service_url, proxy_host = nil, proxy_port=nil)
|
|
4
|
+
@proxy_host = proxy_host
|
|
5
|
+
@proxy_port = proxy_port
|
|
6
|
+
@service_url = service_url
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def register_document_set_b
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def provide_and_register
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create_retrieve_document_set_request(doc_ids=[])
|
|
20
|
+
rdr = RetrieveDocumentSetRequest.new(@service_url,doc_ids)
|
|
21
|
+
rdr.proxy_host = @proxy_host
|
|
22
|
+
rdr.proxy_port = @proxy_port
|
|
23
|
+
rdr
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
end
|
data/lib/xds/helper.rb
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module XDS
|
|
2
|
+
module Helper
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def create_extrinsic_object(builder,id,mime_type,object_type, &block)
|
|
6
|
+
builder.ExtrinsicObject("id"=>id,"mimeType"=>mime_type,"objectType"=>object_type) do
|
|
7
|
+
yield builder if block_given?
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create_external_identifier(builder,id,reg_object,scheme, value, &block)
|
|
12
|
+
|
|
13
|
+
builder.ExternalIdentifier("id"=>id,"registryObject"=>reg_object,"identificationScheme"=>scheme,"value"=>value) do
|
|
14
|
+
yield builder if block_given?
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_name(builder,name,&block)
|
|
19
|
+
builder.Name do
|
|
20
|
+
create_localized_string(builder,name)
|
|
21
|
+
yield builder if block_given?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create_localized_string(builder,value)
|
|
26
|
+
builder.LocalizedString("value"=>value)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def create_slot(builder, name, value_list=[])
|
|
30
|
+
builder.Slot({"name"=>name}) do
|
|
31
|
+
builder.ValueList do
|
|
32
|
+
value_list.each do |val|
|
|
33
|
+
builder.Value(val)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def create_classification(builder,scheme, classified_object,node_rep ,id=UUID.new.generate,&block)
|
|
40
|
+
builder.Classification("classificationScheme"=>scheme,
|
|
41
|
+
"classifiedObject"=>classified_object,
|
|
42
|
+
"nodeRepresentation"=>node_rep,
|
|
43
|
+
"id"=>id) do
|
|
44
|
+
|
|
45
|
+
yield builder if block_given?
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def with_classification(eo_node, classification_scheme, &block)
|
|
50
|
+
if block_given?
|
|
51
|
+
classification = REXML::XPath.first(eo_node, "rim:Classification[@classificationScheme='#{classification_scheme}']", {'rim' => 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0'})
|
|
52
|
+
if classification
|
|
53
|
+
yield classification
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_slot_value(eo_node, slot_name)
|
|
59
|
+
value_node = REXML::XPath.first(eo_node, "rim:Slot[@name='#{slot_name}']/rim:ValueList/rim:Value", {'rim' => 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0'})
|
|
60
|
+
if value_node
|
|
61
|
+
return value_node.text
|
|
62
|
+
else
|
|
63
|
+
return nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def get_slot_values(eo_node, slot_name)
|
|
68
|
+
value_nodes = REXML::XPath.match(eo_node, "rim:Slot[@name='#{slot_name}']/rim:ValueList/rim:Value", {'rim' => 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0'})
|
|
69
|
+
if value_nodes
|
|
70
|
+
return value_nodes.map {|n| n.text}
|
|
71
|
+
else
|
|
72
|
+
return nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def get_external_identifier_value(eo_node, scheme)
|
|
77
|
+
ei_node = REXML::XPath.first(eo_node, "rim:ExternalIdentifier[@identificationScheme='#{scheme}']", {'rim' => 'urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0'})
|
|
78
|
+
ei_node.attributes['value'] if ei_node
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/xds/metadata.rb
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
module XDS
|
|
2
|
+
class Metadata
|
|
3
|
+
|
|
4
|
+
EXTERNAL_ID_SCHEMES={:patient_id=> {:scheme=>'urn:uuid:58a6f841-87b3-4a3e-92fd-a8ffeff98427',
|
|
5
|
+
:value=>'XDSDocumentEntry.patientId'},
|
|
6
|
+
:unique_id=>{:scheme=>'urn:uuid:2e82c1f6-a085-4c72-9da3-8640a32e42ab',
|
|
7
|
+
:value=>'XDSDocumentEntry.uniqueId'}
|
|
8
|
+
}
|
|
9
|
+
include XDS::Helper
|
|
10
|
+
|
|
11
|
+
attr_accessor :author
|
|
12
|
+
attr_accessor :availability_status
|
|
13
|
+
attr_accessor :class_code
|
|
14
|
+
attr_accessor :confidentiality_code
|
|
15
|
+
attr_accessor :creation_time
|
|
16
|
+
attr_accessor :format_code
|
|
17
|
+
attr_accessor :healthcare_facility_type_code
|
|
18
|
+
attr_accessor :language_code
|
|
19
|
+
attr_accessor :mime_type
|
|
20
|
+
attr_accessor :patient_id
|
|
21
|
+
attr_accessor :practice_setting_code
|
|
22
|
+
attr_accessor :service_start_time, :service_stop_time
|
|
23
|
+
attr_accessor :size
|
|
24
|
+
attr_accessor :source_patient_id
|
|
25
|
+
attr_accessor :source_patient_info
|
|
26
|
+
attr_accessor :type_code
|
|
27
|
+
attr_accessor :unique_id
|
|
28
|
+
attr_accessor :uri
|
|
29
|
+
attr_accessor :version_info
|
|
30
|
+
attr_accessor :id
|
|
31
|
+
attr_accessor :ss_unique_id
|
|
32
|
+
attr_accessor :source_id
|
|
33
|
+
attr_accessor :repository_unique_id
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def to_soap(builder)
|
|
37
|
+
@id="urn:uid:#{UUID.new.generate}" unless @id
|
|
38
|
+
|
|
39
|
+
builder.RegistryObjectList("xmlns"=>"urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0") do
|
|
40
|
+
create_extrinsic_object(builder,@id,@mime_type,"urn:uuid:7edca82f-054d-47f2-a032-9b2a5b5186c1") do
|
|
41
|
+
|
|
42
|
+
create_slot(builder,'languageCode', @language_code) if @language_code
|
|
43
|
+
create_slot(builder,'creationTime', @creation_time) if @creation_time
|
|
44
|
+
create_slot(builder,'serviceStartTime', @service_start_time) if @service_start_time
|
|
45
|
+
create_slot(builder,'serviceStopTime', @service_stop_time) if @service_stop_time
|
|
46
|
+
|
|
47
|
+
create_slot(builder,'sourcePatientId', @source_patient_id) if @source_patient_id
|
|
48
|
+
@source_patient_info.try(:to_soap, builder)
|
|
49
|
+
|
|
50
|
+
@version_info.to_soap(builder) if @version_info
|
|
51
|
+
@author.try(:to_soap, builder, @id)
|
|
52
|
+
@class_code.try(:to_soap, builder, @id)
|
|
53
|
+
@confidentiality_code.try(:to_soap, builder, @id)
|
|
54
|
+
@format_code.try(:to_soap, builder, @id)
|
|
55
|
+
@healthcare_facility_type_code.try(:to_soap, builder, @id)
|
|
56
|
+
|
|
57
|
+
@practice_setting_code.try(:to_soap, builder, @id)
|
|
58
|
+
|
|
59
|
+
@type_code.try(:to_soap, builder, @id)
|
|
60
|
+
|
|
61
|
+
external_identifier(builder,:patient_id)
|
|
62
|
+
external_identifier(builder,:unique_id)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
builder.RegistryPackage(:id=>"ss01",:objectType=>"urn:oasis:names:tc:ebxml-regrep:ObjectType:RegistryObject:RegistryPackage") do
|
|
66
|
+
create_slot(builder,"submissionTime",Time.now.strftime('%Y%m%d'))
|
|
67
|
+
|
|
68
|
+
create_classification(builder,"urn:uuid:aa543740-bdda-424e-8c96-df4873be8500","ss01","Initial evaluation","cl01") do
|
|
69
|
+
create_slot(builder,"codingScheme","Connect-a-thon contentTypeCodes")
|
|
70
|
+
create_name(builder,"Initial evaluation")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
create_external_identifier(builder,"ss_ei_01","ss01","urn:uuid:96fdda7c-d067-4183-912e-bf5ee74998a8",ss_unique_id) do |build|
|
|
74
|
+
create_name(builder,"XDSSubmissionSet.uniqueId")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
create_external_identifier(builder,"ss_ei_02","ss01","urn:uuid:554ac39e-e3fe-47fe-b233-965d2a147832",source_id) do |build|
|
|
78
|
+
create_name(builder,"XDSSubmissionSet.sourceId")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
create_external_identifier(builder,"ss_ei_03","ss01","urn:uuid:58a6f841-87b3-4a3e-92fd-a8ffeff98427",@source_patient_info.source_patient_identifier) do |build|
|
|
82
|
+
create_name(builder,"XDSDocumentEntry.patientId")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
create_external_identifier(builder,"ss_ei_04","ss01","urn:uuid:6b5aea1a-874d-4603-a4bc-96a0a7b38446",@source_patient_info.source_patient_identifier) do |build|
|
|
86
|
+
create_name(builder,"XDSSubmissionSet.patientId")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
builder.Classification(:id=>"ss01_class_id",:classificationScheme=>"urn:uuid:a54d6aa5-d40d-43f9-88c5-b4633d873bdd",:classificationNode=>"urn:uuid:a54d6aa5-d40d-43f9-88c5-b4633d873bdd",:classifiedObject=>"ss01")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
builder.Association(:id=>"ass_01",:associationType=>"urn:oasis:names:tc:ebxml-regrep:AssociationType:HasMember",:sourceObject=>"ss01",:targetObject=>@id) do
|
|
95
|
+
create_slot(builder,"SubmissionSetStatus","Original")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def load_from_extrinsic_object(eo_node)
|
|
101
|
+
@author = Author.new
|
|
102
|
+
@author.from_extrinsic_object(eo_node)
|
|
103
|
+
@availability_status = CodedAttribute.new(:availability_status)
|
|
104
|
+
@availability_status.from_extrinsic_object(eo_node)
|
|
105
|
+
@class_code = CodedAttribute.new(:class_code)
|
|
106
|
+
@class_code.from_extrinsic_object(eo_node)
|
|
107
|
+
@confidentiality_code = CodedAttribute.new(:confidentiality_code)
|
|
108
|
+
@confidentiality_code.from_extrinsic_object(eo_node)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@creation_time = get_slot_value(eo_node, 'creationTime')
|
|
112
|
+
|
|
113
|
+
@format_code = CodedAttribute.new(:format_code)
|
|
114
|
+
@format_code.from_extrinsic_object(eo_node)
|
|
115
|
+
@healthcare_facility_type_code = CodedAttribute.new(:healthcare_facility_type_code)
|
|
116
|
+
@healthcare_facility_type_code.from_extrinsic_object(eo_node)
|
|
117
|
+
@language_code = CodedAttribute.new(:language_code)
|
|
118
|
+
@language_code.from_extrinsic_object(eo_node)
|
|
119
|
+
|
|
120
|
+
@mime_type = eo_node.attributes['mimeType']
|
|
121
|
+
|
|
122
|
+
@patient_id = get_external_identifier_value(eo_node, EXTERNAL_ID_SCHEMES[:patient_id][:scheme])
|
|
123
|
+
|
|
124
|
+
@practice_setting_code = CodedAttribute.new(:practice_setting_code)
|
|
125
|
+
@practice_setting_code.from_extrinsic_object(eo_node)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@service_start_time = get_slot_value(eo_node, 'serviceStartTime')
|
|
129
|
+
@service_stop_time = get_slot_value(eo_node, 'serviceStopTime')
|
|
130
|
+
|
|
131
|
+
@source_patient_info = SourcePatientInfo.new
|
|
132
|
+
@source_patient_info.from_extrinsic_object(eo_node)
|
|
133
|
+
|
|
134
|
+
@size = get_slot_value(eo_node, 'size')
|
|
135
|
+
@source_pateint_id = get_slot_value(eo_node, 'sourcePatientId')
|
|
136
|
+
@type_code = CodedAttribute.new(:type_code)
|
|
137
|
+
@type_code.from_extrinsic_object(eo_node)
|
|
138
|
+
@unique_id = get_external_identifier_value(eo_node, EXTERNAL_ID_SCHEMES[:unique_id][:scheme])
|
|
139
|
+
@uri = get_slot_value(eo_node, 'URI')
|
|
140
|
+
@repository_unique_id = get_slot_value(eo_node,"repositoryUniqueId")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def from_hash(hash, affinity_domain_config)
|
|
144
|
+
if hash['author']
|
|
145
|
+
@author = Author.new(hash['author']['institution'], hash['author']['person'], hash['author']['role'], hash['author']['specialty'])
|
|
146
|
+
end
|
|
147
|
+
@availibility_status = hash['availibility_status']
|
|
148
|
+
@class_code = affinity_domain_config.coded_attribute(:class_code, hash['class_code'])
|
|
149
|
+
@confidentiality_code = affinity_domain_config.coded_attribute(:confidentiality_code, hash['confidentiality_code'])
|
|
150
|
+
@creation_time = hash['creation_time']
|
|
151
|
+
@format_code = affinity_domain_config.coded_attribute(:format_code, hash['format_code'])
|
|
152
|
+
@healthcare_facility_type_code = affinity_domain_config.coded_attribute(:healthcare_facility_type_code, hash['healthcare_facility_type_code'])
|
|
153
|
+
@language_code = affinity_domain_config.coded_attribute(:language_code, hash['language_code'])
|
|
154
|
+
@mime_type = hash['mime_type']
|
|
155
|
+
@patient_id = hash['patient_id']
|
|
156
|
+
@practice_setting_code = affinity_domain_config.coded_attribute(:practice_setting_code, hash['practice_setting_code'])
|
|
157
|
+
@service_start_time = hash['service_start_time']
|
|
158
|
+
@service_stop_time = hash['service_stop_time']
|
|
159
|
+
@source_pateint_id = hash['source_pateint_id']
|
|
160
|
+
@source_patient_info = SourcePatientInfo.new(hash['source_patient_info']) if hash['source_patient_info']
|
|
161
|
+
@type_code = affinity_domain_config.coded_attribute(:type_code, hash['type_code'])
|
|
162
|
+
@unique_id = hash['unique_id']
|
|
163
|
+
@uri = hash['uri']
|
|
164
|
+
@version_info = hash['version_info']
|
|
165
|
+
@ss_unique_id = hash['ss_unique_id']
|
|
166
|
+
@source_id = hash['source_id']
|
|
167
|
+
@repository_unique_id = hash['repository_unique_id']
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def external_identifier(builder,name)
|
|
171
|
+
ei_params = EXTERNAL_ID_SCHEMES[name]
|
|
172
|
+
if ei_params
|
|
173
|
+
create_external_identifier(builder,"urn:uid:#{UUID.new.generate}",@id,ei_params[:scheme],self.send(name)) do |build|
|
|
174
|
+
create_name(builder,ei_params[:value])
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|