xdt 1.0.5

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.
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
+