xdt 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-10-11
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,23 @@
1
+ .DS_Store
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/gdt2http
7
+ lib/gdt/field_definitions.rb
8
+ lib/gdt/field_handling.rb
9
+ lib/gdt/parser.rb
10
+ lib/gdt2http.rb
11
+ lib/gdt_interface.rb
12
+ lib/xdt.rb
13
+ lib/xdt/ldt.rb
14
+ lib/xdt/markup.rb
15
+ lib/xdt/xdt_fields.rb
16
+ lib/xdt/xdt_sections.rb
17
+ spec/examples/BARCQPCN.001
18
+ spec/gdt_field_definitions_spec.rb
19
+ spec/gdt_parser_spec.rb
20
+ spec/gdt_spec.rb
21
+ spec/lg_report_spec.rb
22
+ spec/xdt_spec.rb
23
+ xdt.gemspec
@@ -0,0 +1,48 @@
1
+ = xdt
2
+
3
+ * http://levinalex.net/src/xdt
4
+
5
+ == DESCRIPTION:
6
+
7
+ xDT is a library that reads and writes LDT, GDT and BDT data.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * none
12
+
13
+ == SYNOPSIS:
14
+
15
+ no code yet
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * none
20
+
21
+ == INSTALL:
22
+
23
+ * sudo gem install levinalex-xdt
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2008 Levin Alexander
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift './lib'
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require 'xdt'
6
+ require 'spec/rake/spectask'
7
+
8
+ Hoe.new('xdt', Xdt::VERSION) do |p|
9
+ p.developer('Levin Alexander', 'mail@levinalex.net')
10
+ end
11
+
12
+
13
+ Rake.application.instance_eval { @tasks["test"] = nil }
14
+
15
+ Spec::Rake::SpecTask.new do |t|
16
+ t.warning = true
17
+ t.spec_opts = %w(-c -f specdoc)
18
+ end
19
+ task :test => :spec
20
+
21
+
22
+ task :cultivate do
23
+ system "touch Manifest.txt; rake check_manifest | grep -v \"(in \" | patch"
24
+ system "rake debug_gem | grep -v \"(in \" > `basename \\`pwd\\``.gemspec"
25
+ end
26
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__),'..','lib','gdt2http.rb')
4
+
5
+ Gdt::Gdt2Http.new.run!
@@ -0,0 +1,35 @@
1
+ require 'date'
2
+ require File.join(File.dirname(__FILE__), 'field_handling.rb')
3
+
4
+ module Gdt
5
+ class GdtFields < AbstractField
6
+
7
+ field 3000, :nr, "Patientennummer/Patientenkennung", (0..10), :alnum
8
+ field 3100, :name_prefix, "Namenszusatz/Vorsatzwort des Patienten", (0..15)
9
+ field 3101, :last_name, "Name des Patienten", (0..28)
10
+ field 3102, :first_name, "Vorname des Patienten", (0..28)
11
+ field 3103, :birthday, "Geburtsdatum des Patienten", 8, :datum
12
+ field 3104, :title, "Titel des Patienten", (0..15)
13
+ field 3105, :insurance_id, "Versichertennummer des Patienten", (0..12)
14
+ field 3106, :patient_postal_code_city, "Wohnort des Patienten", (0..30)
15
+ field 3107, :patient_street, "Strasse des Patienten", (0..28)
16
+ field 3108, :insurance_type, "Versichertenart MFR", 1, :num
17
+ field 3110, :sex, "Geschlecht des Patienten", 1, :num
18
+ # ...
19
+
20
+ field 8000, :gdt_type, "Satzidentifikation", 4
21
+ field 8100, :gdt_length, "Satzlänge", 5, :num
22
+ field 8315, :receiver_id, "GDT-ID des Empfängers", (0..8) # violates spec, should be "8"
23
+ field 8316, :sender_id, "GDT-ID des Senders", (0..8) # violates the spec, should be "8"
24
+ # ...
25
+
26
+ field 9218, :gdt_version, "Version GDT", 5
27
+
28
+
29
+ # bogus fields to suppress errors
30
+ field 9901, :unknown, "unknown", (0..60), :alnum
31
+ field 8402, :unknown, "unknown", (0..60), :alnum
32
+
33
+
34
+ end
35
+ end
@@ -0,0 +1,81 @@
1
+ require 'date'
2
+ require 'iconv'
3
+
4
+ module Gdt
5
+
6
+ class GdtField < Struct.new(:name, :description, :length, :type, :rules)
7
+ TYPES = {
8
+ :num => lambda { |v| v.to_i },
9
+ :alnum => lambda { |v| ::Iconv.new("UTF-8","CP850").iconv(v) },
10
+ :datum => lambda { |v| ::Date.new(*v.scan(/(..)(..)(....)/)[0].map {|x| x.to_i }.reverse) rescue nil }
11
+ }
12
+
13
+ def type=(value)
14
+ raise ArgumentError, "unrecognized data type '#{value.inspect}'" unless TYPES.include?(value)
15
+ @type = value
16
+ end
17
+ def type
18
+ @type || :alnum
19
+ end
20
+
21
+ def length=(value)
22
+ if value
23
+ @length = (Range === value) ? value : Range.new(value,value)
24
+ else
25
+ @length = nil
26
+ end
27
+ end
28
+
29
+ def verify_and_convert(value)
30
+ # check length
31
+ #
32
+ if @length
33
+ message = "the field #{name.inspect} does not have the correct length, expected (#{@length.inspect})"
34
+ # ignore length checks for now
35
+ # raise ArgumentError, message unless @length.include?(value.length)
36
+ end
37
+ TYPES[self.type].call(value)
38
+ end
39
+
40
+ end
41
+
42
+ class AbstractField
43
+
44
+ def self.field(gdt_id, name, description, length, type = :alnum, rules = nil)
45
+ field = (fields[gdt_id] ||= GdtField.new)
46
+
47
+ field.name = name
48
+ field.type = type
49
+ field.length = length
50
+
51
+ define_method name do
52
+ values[name]
53
+ end
54
+ end
55
+
56
+ def self.lookup(field_id)
57
+ @gdt_fields[field_id].name
58
+ end
59
+ def self.fields
60
+ @gdt_fields ||= Hash.new
61
+ end
62
+
63
+ def values
64
+ @values ||= Hash.new
65
+ end
66
+
67
+ def set_field(gdt_id, value)
68
+ field = self.class.fields[gdt_id]
69
+ raise ArgumentError, "undefined field '#{gdt_id}'" unless field
70
+
71
+ values[field.name] = field.verify_and_convert(value)
72
+ end
73
+
74
+ def initialize(gdt_hash)
75
+ gdt_hash.each { |gdt_id, value|
76
+ set_field(gdt_id, value)
77
+ }
78
+ end
79
+ end
80
+ end
81
+
@@ -0,0 +1,36 @@
1
+
2
+ module Gdt
3
+
4
+ class ParseError < ArgumentError
5
+ end
6
+
7
+ class Parser
8
+ def self.parse(string)
9
+ # canonical line endings
10
+ string.gsub!("\r\n","\n")
11
+
12
+ string.split(/\n/).
13
+ # ignore empty lines and lines consisting only of whitespace
14
+ delete_if { |line| line =~ /^\s*$/ }.
15
+ inject({}) do |h, line|
16
+ # parse the line into tokens
17
+ #
18
+ length, type, data = line.scan(/(\d{3})(\d{4})(.*)/).first
19
+
20
+ raise ParseError, "line does not match expected GDT format: '#{line}'" unless length && type && data
21
+
22
+ length = length.to_i
23
+ type = type.to_i
24
+
25
+ # 3 bytes length + 4 bytes record id + data length (bytes) + CR LF
26
+ expected_length = 3 + 4 + data.length + 2
27
+
28
+ raise ParseError, "wrong length in GDT data: '#{line}'" unless length == expected_length
29
+
30
+ h[type] = data
31
+ h
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'net/http'
5
+ require 'yaml'
6
+
7
+ require File.join(File.dirname(__FILE__),'gdt_interface.rb')
8
+
9
+ module Gdt
10
+ ConfigFilename = ".gdt2http"
11
+ ConfigFile = File.join(ENV['HOME'] || ENV['APPDATA'], ConfigFilename)
12
+
13
+ # defaults are used when they are not overwritten in a config file
14
+ # or with command line options
15
+ #
16
+ DefaultConfig = {
17
+ :files => ["**/*.GDT"],
18
+ :endpoint => "http://localhost:3000/gdt",
19
+ :delete_files => true
20
+ }
21
+
22
+ class Gdt2Http
23
+
24
+ # load configuration from configfile, merge with
25
+ # default options
26
+ #
27
+ def load_configuration
28
+ # try to read configuration from file
29
+ @options_from_file = YAML.load_file(ConfigFile) || {} rescue {}
30
+
31
+ # if an option is not given on the command line
32
+ # it is taken from the config file, or the default is used
33
+ @options = Hash.new() { |h,k| @options_from_file[k] || DefaultConfig[k] }
34
+ end
35
+
36
+ # parse command line options
37
+ #
38
+ def initialize
39
+ load_configuration
40
+
41
+ @opts = OptionParser.new do |opts|
42
+ opts.on "-V","--version","Display version and exit" do
43
+ puts "#{self.class} #{::Gdt::VERSION}"
44
+ exit
45
+ end
46
+ opts.on "-f", "--files PATTERN", Array,
47
+ "a list of files or shell globs to look for",
48
+ "default is '**/*.GDT'" do |arg|
49
+ @options[:files] = arg
50
+ end
51
+ opts.on "-u", "--uri URI", "URI of the HTTP-Endpoint to which the parsed data is sent" do |arg|
52
+ @options[:endpoint] = arg
53
+ end
54
+ opts.on_tail "-p", "--print-config", "Print the current configuration",
55
+ "in a format that can be used as a configuration file" do
56
+ puts @options_from_file.merge(@options).to_yaml
57
+ exit
58
+ end
59
+ end
60
+ end
61
+
62
+ def files
63
+ @options[:files].map { |p| Dir.glob(p) }.flatten.compact.uniq
64
+ end
65
+
66
+ def handle_file(filename)
67
+ # open and parse the given file
68
+ str = File.read(filename)
69
+
70
+ begin
71
+ data = Gdt.new(str)
72
+
73
+ begin
74
+ res = ::Net::HTTP.post_form(URI.parse(@options[:endpoint]), data.to_hash )
75
+ puts res.header.to_hash.map { |k,v| "#{k}: #{v}" }
76
+ puts
77
+ case res
78
+ when ::Net::HTTPSuccess
79
+ File.delete(filename) if @options[:delete_files]
80
+ puts res.body
81
+ when ::Net::HTTPClientError
82
+ warn "Client Error"
83
+ when ::Net::HTTPServerError
84
+ warn "Server Error"
85
+ end
86
+
87
+ rescue ::Errno::ECONNREFUSED
88
+ puts "Unable to connect to server '#{@options[:endpoint]}' (connection refused)"
89
+ end
90
+ rescue ParseError => e
91
+ warn "Parse error in '#{filename}'"
92
+ end
93
+ end
94
+
95
+ # run the application
96
+ #
97
+ def run!(args = ARGV)
98
+ @opts.parse!(args)
99
+ files.each { |f|
100
+ handle_file(f)
101
+ }
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,20 @@
1
+ GDT_ROOT = File.dirname(File.expand_path(__FILE__))
2
+
3
+ require File.join(GDT_ROOT, 'gdt', 'parser.rb')
4
+ require File.join(GDT_ROOT, 'gdt', 'field_definitions.rb')
5
+
6
+
7
+ module Gdt
8
+ VERSION = '0.0.8'
9
+
10
+ class Gdt
11
+ def initialize(string)
12
+ @data = GdtFields.new( Parser.parse(string))
13
+ end
14
+
15
+ def to_hash
16
+ @data.values
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+
3
+ require 'xdt/markup'
4
+ require 'xdt/ldt'
5
+
6
+ module Xdt
7
+ VERSION = '1.0.5'
8
+ end
@@ -0,0 +1,80 @@
1
+ # class Xdt::Ldt
2
+ # ldt_block_type '0020', :media_start, "Datenträger Header"
3
+ # ldt_block_type '0021', :media_end, "Datenträger Abschluss"
4
+ # ldt_block_type '8220', :l_package_start, "L-Datenpaket-Header"
5
+ # ldt_block_type '8221', :l_package_end, "L-Datenpaket-Abschluss"
6
+ # ldt_block_type '8230', :p_package_start, "P-Datenpaket-Header"
7
+ # ldt_block_type '8231', :p_package_end, "P-Datenpaket-Abschluss"
8
+ # ldt_block_type '8201', :lab_report, "Labor-Facharzt-Bericht"
9
+ # ldt_block_type '8202', :lg_report, "LG-Bericht"
10
+ # ldt_block_type '8203', :microbiology_report, "Mikrobiologie-Bericht"
11
+ # ldt_block_type '8204', :referrer_report, "Facharzt-Bericht 'sonstige Einsendepraxen'"
12
+ # ldt_block_type '8218', :electronic_referral, "Elektronische Überweisung"
13
+ # ldt_block_type '8219', :lab_request, "Auftrag an eine Laborgemeinschaft"
14
+ # end
15
+
16
+ require 'date'
17
+ require 'xdt/markup'
18
+
19
+ module Xdt
20
+ module Ldt
21
+ module Package
22
+ end
23
+
24
+ class LGReport
25
+
26
+ # only write the file if it contains any sections
27
+ #
28
+ def write_file(filename)
29
+ return false unless @sections.length > 2
30
+
31
+ File.open(filename, "w+") do |f|
32
+ f.write self.to_s
33
+ end
34
+
35
+ return true
36
+ end
37
+
38
+ def section(id, &blk)
39
+ @sections << Xdt::Section.new(id, &blk)
40
+ end
41
+
42
+ def initialize
43
+ @sections = []
44
+
45
+ section("8220") do |s|
46
+ s.field("9211", "07/99")
47
+ # s.field("0201", "") # Arztnummer
48
+ s.field("0203", "Alexander") # Arztname
49
+ s.field("0204", "Nuklearmediziner") # Arztgruppe
50
+ s.field("0205", "Schönhauser Allee 82") # Strasse
51
+ s.field("0206", "10439 Berlin") # PLZ Ort
52
+ s.field("8300", "LABOR Schoenhauser Allee 82")
53
+ # s.field("0101", "") # KBV Prüfnummer
54
+ s.field("9106", "3") # Charset (iso-8859-1)
55
+ s.field("8312", "1") # Kundennummer
56
+ s.field("9103", Date.today.strftime("%D%M%Y"))
57
+ end
58
+
59
+ yield self if block_given?
60
+
61
+ section("8221") do |s|
62
+ overhead = 44
63
+ s.field("9202", (length + overhead).to_s.rjust(8,"0"))
64
+ end
65
+
66
+ end
67
+
68
+ def length
69
+ @sections.inject(0) { |sum, section| sum + section.length }
70
+ end
71
+
72
+ def to_s
73
+ @sections.map { |pkg| pkg.to_s }.join
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+
80
+
@@ -0,0 +1,7 @@
1
+ require 'xdt/xdt_fields'
2
+ require 'xdt/xdt_sections'
3
+
4
+ module Xdt
5
+ class Package
6
+ end
7
+ end
@@ -0,0 +1,75 @@
1
+ require 'xdt/markup'
2
+
3
+ module Xdt
4
+ class FieldType
5
+ def initialize(id, name, title, length, type = :string)
6
+ @id = id.to_i
7
+ @name = name
8
+ @title = title
9
+ @type = type
10
+ end
11
+
12
+ def valid?(contents)
13
+ true
14
+ end
15
+ end
16
+
17
+ module FieldHandling
18
+ def define_field(id, *args)
19
+ @defined_fields ||= Hash.new { |h,k| raise "Redefined Field #{k}" }
20
+ @defined_fields[id.to_i] = Xdt::FieldType.new(id, *args)
21
+ end
22
+ end
23
+
24
+ module Fields
25
+ def included(other)
26
+ define_field 101, :kbv_id, "KBV-Prüfnummer", 8, :alnum
27
+
28
+ define_field 201, :physician_id, "Arztnummer", (7..9), :num
29
+ define_field 203, :physician_name, "Arztname", (0..60), :alnum
30
+ define_field 204, :physician_define_field, "Arztgruppe", (0..60), :alnum
31
+ define_field 205, :street, "Strasse", (0..60), :alnum
32
+ define_field 206, :zip, "PLZ Ort", (0..60), :alnum
33
+
34
+ define_field 3000, :nr, "Patientennummer/Patientenkennung", (0..10), :alnum
35
+ define_field 3100, :name_prefix, "Namenszusatz/Vorsatzwort des Patienten", (0..15)
36
+ define_field 3101, :last_name, "Name des Patienten", (0..28)
37
+ define_field 3102, :first_name, "Vorname des Patienten", (0..28)
38
+ define_field 3103, :birthday, "Geburtsdatum des Patienten", 8, :date
39
+ define_field 3104, :title, "Titel des Patienten", (0..15)
40
+ define_field 3105, :insurance_id, "Versichertennummer des Patienten", (0..12)
41
+ define_field 3106, :patient_postal_code_city, "Wohnort des Patienten", (0..30)
42
+ define_field 3107, :patient_street, "Strasse des Patienten", (0..28)
43
+ define_field 3108, :insurance_type, "Versichertenart MFR", 1, :num
44
+ define_field 3110, :sex, "Geschlecht des Patienten", 1, :num
45
+
46
+ define_field 8000, :gdt_type, "Satzidentifikation", 4
47
+ define_field 8100, :gdt_length, "Satzlänge", 5, :num
48
+ define_field 8315, :receiver_id, "GDT-ID des Empfängers", (0..8) # violates spec, should be "8"
49
+ define_field 8316, :sender_id, "GDT-ID des Senders", (0..8) # violates the spec, should be "8"
50
+
51
+ define_field 9218, :gdt_version, "Version GDT", 5
52
+ end
53
+ end
54
+
55
+ class Field
56
+ class << self
57
+ include Xdt::FieldHandling
58
+ end
59
+
60
+ include Xdt::Fields
61
+
62
+ def initialize(type, data)
63
+ @id = type
64
+ @data = data.to_s
65
+ end
66
+
67
+ def length
68
+ @data.length + 9
69
+ end
70
+
71
+ def to_s
72
+ "#{ '%03d' % self.length }#{ '%04d' % @id.to_i }#{@data}\x0D\x0A"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,63 @@
1
+ module Xdt
2
+ class SectionType
3
+ def initialize(id, name, title, length, type = :string)
4
+ @id = id.to_i
5
+ @name = name
6
+ @title = title
7
+ @type = type
8
+ end
9
+
10
+ def valid?(contents)
11
+ true
12
+ end
13
+ end
14
+
15
+ module SectionHandling
16
+ def define_section(id, name, title, &block)
17
+ end
18
+ end
19
+
20
+ class Section
21
+ class << self
22
+ include Xdt::SectionHandling
23
+
24
+ alias [] new
25
+ end
26
+
27
+ define_section 8220, :l_packet_header, "L-Datenpaket-Header" do |s|
28
+ s.field [9211, 201, 203, 204, 205, 206, 8300, 101, 9106, 8312, 9103], :cardinality => '1'
29
+ s.field 9472, :cardinality => 'n'
30
+ s.field 9300, :cardinality => '?'
31
+ s.field 9301, :cardinality => '?'
32
+ end
33
+
34
+ define_section 8221, :l_packet_footer, "L-Datenpaket Abschluss" do |s|
35
+ s.field 9202, :cardinality => '1', :default => proc { |section| section.length + 44 }
36
+ end
37
+
38
+ def initialize(type)
39
+ @type = type
40
+ @fields = []
41
+ yield self if block_given?
42
+ end
43
+
44
+ def field(*args)
45
+ @fields << Field.new(*args)
46
+ end
47
+
48
+ def length
49
+ to_s.length
50
+ end
51
+
52
+ def to_s
53
+ header_length = 27
54
+
55
+ data = @fields.map { |field| field.to_s }.join
56
+ header = Field.new("8000", '%04d' % @type.to_i).to_s +
57
+ Field.new("8100", '%05d' % (data.length + header_length) ).to_s
58
+
59
+ header + data
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,14 @@
1
+ 01380006301
2
+ 014810000228
3
+ 0168315Barcode
4
+ 0158316QPCnet
5
+ 014921802.00
6
+ 011300098
7
+ 0153101Sierra
8
+ 0163102Rudolph
9
+ 017310313041928
10
+ 0193105123 130328
11
+ 02731064000 D�sseldorf 12
12
+ 0313107Richard-Wagner-Str. 11
13
+ 01031083
14
+ 01031101
@@ -0,0 +1,106 @@
1
+ context "Gdt field ids should map to names" do
2
+ field_names = {
3
+ # 0102
4
+ # 0103
5
+ # 0132
6
+ 3000 => :nr,
7
+ 3100 => :name_prefix,
8
+ 3101 => :last_name,
9
+ 3102 => :first_name,
10
+ 3103 => :birthday,
11
+ 3104 => :title,
12
+ 3105 => :insurance_id,
13
+ 3106 => :patient_postal_code_city,
14
+ 3107 => :patient_street,
15
+ 3108 => :insurance_type,
16
+ 3110 => :sex,
17
+ # 3622
18
+ # 3623
19
+ # 3628
20
+ # 6200
21
+ 8000 => :gdt_type,
22
+ 8100 => :gdt_length,
23
+ 8315 => :receiver_id,
24
+ 8316 => :sender_id,
25
+
26
+ 9218 => :gdt_version
27
+ }
28
+
29
+ field_names.each do |id, name|
30
+ specify("#{id.to_s} => #{name.inspect}") do
31
+ Gdt::GdtFields.lookup(id).should == name
32
+ end
33
+ end
34
+ end
35
+
36
+ context "Parsing a Hash with Gdt-Data" do
37
+ setup do
38
+ @parsed_data = Gdt::GdtFields.new( { 3000 => "98", 3101 => "Sierra", 3110 => "2" } )
39
+ end
40
+
41
+ specify "should convert field IDs to names" do
42
+ @parsed_data.last_name.should == "Sierra"
43
+ @parsed_data.nr.should == "98"
44
+ end
45
+ specify "should convert numeric fields to numbers" do
46
+ @parsed_data.sex.should == 2
47
+ end
48
+ end
49
+
50
+ context "Unknown field IDs" do
51
+ setup do
52
+ @c = Class.new(Gdt::AbstractField) do |c|
53
+ # no fields are defined
54
+ end
55
+ end
56
+ specify "should raise an error on parsing" do
57
+ lambda { @c.new( { 42 => "data" } ) }.should raise_error(ArgumentError)
58
+ end
59
+ end
60
+
61
+ context "Fields with a fixed length" do
62
+ setup do
63
+ @c = Class.new(Gdt::AbstractField) do |c|
64
+ c.field 1, :number, "some number", 2, :num
65
+ end
66
+ end
67
+
68
+ specify "should raise no error if the length is correct" do
69
+ @c.new( { 1 => "03" } ).number.should == 3
70
+ end
71
+ #specify "should raise an error if the length is to small or too long" do
72
+ # lambda { @c.new( { 1 => "0" } ) }.should raise_error(ArgumentError)
73
+ # lambda { @c.new( { 1 => "045" } ) }.should raise_error(ArgumentError)
74
+ #end
75
+ end
76
+
77
+ context "Fields with a maximum length" do
78
+ setup do
79
+ @c = Class.new(Gdt::AbstractField) do |c|
80
+ c.field 1, :data, "a string", (0..21), :alnum
81
+ end
82
+ end
83
+
84
+ specify "should allow empty strings" do
85
+ @c.new( { 1 => "" } ).data.should == ""
86
+ end
87
+ specify "should allow fields inside the bounds" do
88
+ lambda { @c.new( { 1 => "exactly 21 characters" } ).data }.should_not raise_error
89
+ lambda { @c.new( { 1 => "fewer characters" } ).data }.should_not raise_error
90
+ end
91
+ #specify "should raise an error if length is too big" do
92
+ # lambda { @c.new( { 1 => "exactly 22 characters!" } ).data }.should raise_error(ArgumentError)
93
+ #end
94
+ end
95
+
96
+ context "Date fields" do
97
+ setup do
98
+ @c = Class.new(Gdt::AbstractField) do |c|
99
+ c.field 1, :data, "a date field", 8, :datum
100
+ end
101
+ end
102
+
103
+ specify "should return an instance of the Date class" do
104
+ @c.new( { 1 => "31011994" }).data.should == Date.parse("1994-01-31")
105
+ end
106
+ end
@@ -0,0 +1,50 @@
1
+ context "Valid GDT tokens" do
2
+ setup do
3
+ @line = "01380006301\r\n"
4
+ end
5
+
6
+ specify "should parse without errors" do
7
+ lambda { Gdt::Parser.parse(@line) }.should_not raise_error
8
+ end
9
+
10
+ specify "should return a hash with the correct data" do
11
+ Gdt::Parser.parse(@line).should == {8000 => "6301"}
12
+ end
13
+
14
+ specify "parser should ignore empty lines" do
15
+ result = nil
16
+ lambda { result = Gdt::Parser.parse(" \r\n\r\n ") }.should_not raise_error
17
+ result.should == {}
18
+ end
19
+ end
20
+
21
+ context "Malformed data" do
22
+ specify "should raise an exception on malformed length" do
23
+ lambda { Gdt::Parser.parse("01480006301") }.should raise_error(Gdt::ParseError)
24
+ end
25
+
26
+ specify "that does not conform to the format at all should raise an exception" do
27
+ lambda { Gdt::Parser.parse("useless garbage\r\nwith multiple lines\r\n") }.should raise_error(Gdt::ParseError)
28
+ end
29
+ end
30
+
31
+ context "a valid Gdt file from Quincy PCNet" do
32
+ setup do
33
+ @gdt_data = File.read(File.dirname(__FILE__) + '/examples/BARCQPCN.001')
34
+ end
35
+
36
+ specify "should parse without error" do
37
+ lambda { Gdt::Parser.parse( @gdt_data ) }.should_not raise_error
38
+ end
39
+
40
+ specify "should contain 14 fields" do
41
+ Gdt::Parser.parse( @gdt_data ).length.should equal(14)
42
+ end
43
+
44
+ specify "should contain correct data" do
45
+ Gdt::Parser.parse(@gdt_data).should satisfy { |gdt|
46
+ gdt[3000] == "98" && gdt[8000] == "6301" && gdt[3101] == "Sierra"
47
+ }
48
+ end
49
+
50
+ end
@@ -0,0 +1,15 @@
1
+ require 'lib/gdt_interface.rb'
2
+
3
+ context "reading GDT data from a file" do
4
+ def read_file
5
+ Gdt::Gdt.new(File.read('./spec/examples/BARCQPCN.001'))
6
+ end
7
+
8
+ specify "should work without errors" do
9
+ lambda { Gdt::Gdt.new(File.read('./spec/examples/BARCQPCN.001')) }.should_not raise_error
10
+ end
11
+
12
+ specify "data should be representable as a hash" do
13
+ read_file.to_hash.should be_instance_of(Hash)
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+
2
+ describe "creating an LG-report" do
3
+ before do
4
+ @lg = Xdt::Ldt::LGReport.new do |lg|
5
+ lg.section("8202") do |s|
6
+ s.field("8310", "12345") # Anforderungs-ID
7
+ s.field("8301", "09062008") # Eingangsdatum im Labor
8
+ s.field("8302", "10062008") # Berichtsdatum
9
+ s.field("3000", "98") # PAT-ID (Nospec)
10
+ s.field("3103", "10111982") # Geburtsdatum des Pat
11
+ s.field("8401", "E") # Befundart
12
+
13
+ s.field("8410", "TPO") # Test-Ident
14
+ s.field("8411", "ANTITPO") # Testbezeichnung
15
+ s.field("8418", "K") # Tststatus (Fehlt, Korrigiert, Berichtigt)
16
+ s.field("8420", "12.4")
17
+ s.field("8421", "U/l") # Einkeit
18
+ s.field("8480", "Ergebnistext") # Ergebnistext
19
+
20
+ end
21
+ end
22
+ end
23
+
24
+ it "should not raise any errors" do
25
+ proc { @lg.to_s }.should_not raise_error
26
+ end
27
+
28
+ it "should have the correct string representation" do
29
+ @lg.to_s.should == <<-EOF
30
+ 01380008220
31
+
32
+ EOF
33
+ end
34
+
35
+ it "should have correct length" do
36
+ @lg.to_s[/9202\d{8}/][-8..-1].to_i.should == @lg.to_s.length
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ require 'lib/xdt'
2
+
3
+ describe "an XDT record with an ID and some data" do
4
+ before do
5
+ @field = Xdt::Field.new("8000", "8221")
6
+ end
7
+
8
+ it "should have a string representation that includes length and ends in CR LF" do
9
+ @field.to_s.should == "01380008221\r\n"
10
+ end
11
+ end
12
+
13
+ describe "creating a XDT block" do
14
+ before do
15
+ @block = Xdt::Section.new("0020") do |b|
16
+ b.field "9105", "123"
17
+ end
18
+ end
19
+
20
+ it "should have a string representation where the length field exists and has the correct value" do
21
+ @block.to_s.should == "01380000020\r\n014810000039\r\n0129105123\r\n"
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{xdt}
3
+ s.version = "1.0.5"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Levin Alexander"]
7
+ s.date = %q{2008-11-10}
8
+ s.default_executable = %q{gdt2http}
9
+ s.description = %q{xDT is a library that reads and writes LDT, GDT and BDT data.}
10
+ s.email = ["mail@levinalex.net"]
11
+ s.executables = ["gdt2http"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
13
+ s.files = [".DS_Store", "History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/gdt2http", "lib/gdt/field_definitions.rb", "lib/gdt/field_handling.rb", "lib/gdt/parser.rb", "lib/gdt2http.rb", "lib/gdt_interface.rb", "lib/xdt.rb", "lib/xdt/ldt.rb", "lib/xdt/markup.rb", "lib/xdt/xdt_fields.rb", "lib/xdt/xdt_sections.rb", "spec/examples/BARCQPCN.001", "spec/gdt_field_definitions_spec.rb", "spec/gdt_parser_spec.rb", "spec/gdt_spec.rb", "spec/lg_report_spec.rb", "spec/xdt_spec.rb", "xdt.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://levinalex.net/src/xdt}
16
+ s.rdoc_options = ["--main", "README.txt"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{xdt}
19
+ s.rubygems_version = %q{1.2.0}
20
+ s.summary = %q{xDT is a library that reads and writes LDT, GDT and BDT data.}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if current_version >= 3 then
27
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
28
+ else
29
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xdt
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 5
10
+ version: 1.0.5
11
+ platform: ruby
12
+ authors:
13
+ - Levin Alexander
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2008-11-10 00:00:00 +01:00
19
+ default_executable: gdt2http
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: hoe
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 55
30
+ segments:
31
+ - 1
32
+ - 8
33
+ - 0
34
+ version: 1.8.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: xDT is a library that reads and writes LDT, GDT and BDT data.
38
+ email:
39
+ - mail@levinalex.net
40
+ executables:
41
+ - gdt2http
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - History.txt
46
+ - Manifest.txt
47
+ - README.txt
48
+ files:
49
+ - .DS_Store
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.txt
53
+ - Rakefile
54
+ - bin/gdt2http
55
+ - lib/gdt/field_definitions.rb
56
+ - lib/gdt/field_handling.rb
57
+ - lib/gdt/parser.rb
58
+ - lib/gdt2http.rb
59
+ - lib/gdt_interface.rb
60
+ - lib/xdt.rb
61
+ - lib/xdt/ldt.rb
62
+ - lib/xdt/markup.rb
63
+ - lib/xdt/xdt_fields.rb
64
+ - lib/xdt/xdt_sections.rb
65
+ - spec/examples/BARCQPCN.001
66
+ - spec/gdt_field_definitions_spec.rb
67
+ - spec/gdt_parser_spec.rb
68
+ - spec/gdt_spec.rb
69
+ - spec/lg_report_spec.rb
70
+ - spec/xdt_spec.rb
71
+ - xdt.gemspec
72
+ has_rdoc: true
73
+ homepage: http://levinalex.net/src/xdt
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --main
79
+ - README.txt
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project: xdt
103
+ rubygems_version: 1.3.7
104
+ signing_key:
105
+ specification_version: 2
106
+ summary: xDT is a library that reads and writes LDT, GDT and BDT data.
107
+ test_files: []
108
+