rtp-connect 1.0
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/CHANGELOG.rdoc +9 -0
- data/COPYING +674 -0
- data/README.rdoc +128 -0
- data/lib/rtp-connect.rb +20 -0
- data/lib/rtp-connect/constants.rb +58 -0
- data/lib/rtp-connect/control_point.rb +444 -0
- data/lib/rtp-connect/extended_field.rb +127 -0
- data/lib/rtp-connect/field.rb +578 -0
- data/lib/rtp-connect/logging.rb +158 -0
- data/lib/rtp-connect/methods.rb +31 -0
- data/lib/rtp-connect/plan.rb +545 -0
- data/lib/rtp-connect/prescription.rb +218 -0
- data/lib/rtp-connect/record.rb +37 -0
- data/lib/rtp-connect/ruby_extensions.rb +82 -0
- data/lib/rtp-connect/site_setup.rb +227 -0
- data/lib/rtp-connect/variables.rb +19 -0
- data/lib/rtp-connect/version.rb +6 -0
- metadata +113 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
module RTP
|
2
|
+
|
3
|
+
# This module handles logging functionality.
|
4
|
+
#
|
5
|
+
# Logging functionality uses the Standard library's Logger class.
|
6
|
+
# To properly handle progname, which inside the RTP module is simply
|
7
|
+
# "RTP", in all cases, we use an implementation with a proxy class.
|
8
|
+
#
|
9
|
+
# === Examples
|
10
|
+
#
|
11
|
+
# require 'rtp-connect'
|
12
|
+
# include RTP
|
13
|
+
#
|
14
|
+
# # Logging to STDOUT with DEBUG level:
|
15
|
+
# RTP.logger = Logger.new(STDOUT)
|
16
|
+
# RTP.logger.level = Logger::DEBUG
|
17
|
+
#
|
18
|
+
# # Logging to a file:
|
19
|
+
# RTP.logger = Logger.new('my_logfile.log')
|
20
|
+
#
|
21
|
+
# # Combine an external logger with RTP:
|
22
|
+
# logger = Logger.new(STDOUT)
|
23
|
+
# logger.progname = "MY_APP"
|
24
|
+
# RTP.logger = logger
|
25
|
+
# # Now you can call the logger in the following ways:
|
26
|
+
# RTP.logger.info "Message" # => "RTP: Message"
|
27
|
+
# RTP.logger.info("MY_MODULE) {"Message"} # => "MY_MODULE: Message"
|
28
|
+
# logger.info "Message" # => "MY_APP: Message"
|
29
|
+
#
|
30
|
+
# For more information, please read the Standard library Logger documentation.
|
31
|
+
#
|
32
|
+
module Logging
|
33
|
+
|
34
|
+
require 'logger'
|
35
|
+
|
36
|
+
# Inclusion hook to make the ClassMethods available to whatever
|
37
|
+
# includes the Logging module, i.e. the RTP module.
|
38
|
+
#
|
39
|
+
def self.included(base)
|
40
|
+
base.extend(ClassMethods)
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
|
45
|
+
# We use our own ProxyLogger to achieve the features wanted for RTP logging,
|
46
|
+
# e.g. using RTP as progname for messages logged within the RTP module
|
47
|
+
# (for both the Standard logger as well as the Rails logger), while still allowing
|
48
|
+
# a custom progname to be used when the logger is called outside the RTP module.
|
49
|
+
#
|
50
|
+
class ProxyLogger
|
51
|
+
|
52
|
+
# Creating the ProxyLogger instance.
|
53
|
+
#
|
54
|
+
# === Parameters
|
55
|
+
#
|
56
|
+
# * <tt>target</tt> -- A Logger instance (e.g. Standard Logger or ActiveSupport::BufferedLogger).
|
57
|
+
#
|
58
|
+
def initialize(target)
|
59
|
+
@target = target
|
60
|
+
end
|
61
|
+
|
62
|
+
# Catches missing methods.
|
63
|
+
# In our case, the methods of interest are the typical logger methods,
|
64
|
+
# i.e. log, info, fatal, error, debug, where the arguments/block are
|
65
|
+
# redirected to the logger in a specific way so that our stated logger
|
66
|
+
# features are achieved (this behaviour depends on the logger
|
67
|
+
# (Rails vs Standard) and in the case of Standard logger,
|
68
|
+
# whether or not a block is given).
|
69
|
+
#
|
70
|
+
# === Examples
|
71
|
+
#
|
72
|
+
# # Inside the RTP module or an external class with 'include RTP::Logging':
|
73
|
+
# logger.info "message"
|
74
|
+
#
|
75
|
+
# # Calling from outside the RTP module:
|
76
|
+
# RTP.logger.info "message"
|
77
|
+
#
|
78
|
+
def method_missing(method_name, *args, &block)
|
79
|
+
if method_name.to_s =~ /(log|debug|info|warn|error|fatal)/
|
80
|
+
# Rails uses it's own buffered logger which does not
|
81
|
+
# work with progname + block as the standard logger does:
|
82
|
+
if defined?(Rails)
|
83
|
+
@target.send(method_name, "RTP: #{args.first}")
|
84
|
+
elsif block_given?
|
85
|
+
@target.send(method_name, *args) { yield }
|
86
|
+
else
|
87
|
+
@target.send(method_name, "RTP") { args.first }
|
88
|
+
end
|
89
|
+
else
|
90
|
+
@target.send(method_name, *args, &block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# The logger class variable (must be initialized
|
97
|
+
# before it is referenced by the object setter).
|
98
|
+
#
|
99
|
+
@@logger = nil
|
100
|
+
|
101
|
+
# The logger object setter.
|
102
|
+
# This method is used to replace the default logger instance with
|
103
|
+
# a custom logger of your own.
|
104
|
+
#
|
105
|
+
# === Parameters
|
106
|
+
#
|
107
|
+
# * <tt>l</tt> -- A Logger instance (e.g. a custom standard Logger).
|
108
|
+
#
|
109
|
+
# === Examples
|
110
|
+
#
|
111
|
+
# # Create a logger which ages logfile once it reaches a certain size,
|
112
|
+
# # leaves 10 "old log files" with each file being about 1,024,000 bytes:
|
113
|
+
# RTP.logger = Logger.new('foo.log', 10, 1024000)
|
114
|
+
#
|
115
|
+
def logger=(l)
|
116
|
+
@@logger = ProxyLogger.new(l)
|
117
|
+
end
|
118
|
+
|
119
|
+
# The logger object getter.
|
120
|
+
# Returns the logger class variable, if defined.
|
121
|
+
# If not defined, sets up the Rails logger (if in a Rails environment),
|
122
|
+
# or a Standard logger if not.
|
123
|
+
#
|
124
|
+
# === Examples
|
125
|
+
#
|
126
|
+
# # Inside the RTP module (or a class with 'include RTP::Logging'):
|
127
|
+
# logger # => Logger instance
|
128
|
+
#
|
129
|
+
# # Accessing from outside the RTP module:
|
130
|
+
# RTP.logger # => Logger instance
|
131
|
+
#
|
132
|
+
def logger
|
133
|
+
@@logger ||= lambda {
|
134
|
+
if defined?(Rails)
|
135
|
+
ProxyLogger.new(Rails.logger)
|
136
|
+
else
|
137
|
+
l = Logger.new(STDOUT)
|
138
|
+
l.level = Logger::INFO
|
139
|
+
ProxyLogger.new(l)
|
140
|
+
end
|
141
|
+
}.call
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
# A logger object getter.
|
147
|
+
# Forwards the call to the logger class method of the Logging module.
|
148
|
+
#
|
149
|
+
def logger
|
150
|
+
self.class.logger
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
# Include the Logging module so we can use RTP.logger.
|
156
|
+
include Logging
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RTP
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
#--
|
6
|
+
# Module methods:
|
7
|
+
#++
|
8
|
+
|
9
|
+
# Computes the CRC checksum of the given line and verifies that
|
10
|
+
# this value corresponds with the checksum given at the end of the line.
|
11
|
+
# Raises an error if the two values does not match.
|
12
|
+
#
|
13
|
+
# === Parameters
|
14
|
+
#
|
15
|
+
# * <tt>line</tt> -- An single line string from an RTPConnect ascii file.
|
16
|
+
#
|
17
|
+
def verify(line)
|
18
|
+
last_comma_pos = line.rindex(',')
|
19
|
+
raise ArgumentError, "Invalid line encountered; No comma present in the string: #{line}" unless last_comma_pos
|
20
|
+
string_to_check = line[0..last_comma_pos]
|
21
|
+
string_remaining = line[(last_comma_pos+1)..-1]
|
22
|
+
raise ArgumentError, "Invalid line encountered; Valid checksum missing at end of string: #{string_remaining}" unless string_remaining.length > 3
|
23
|
+
checksum_extracted = string_remaining.value.to_i
|
24
|
+
checksum_computed = string_to_check.checksum
|
25
|
+
raise ArgumentError, "Invalid line encountered: Specified checskum #{checksum_extracted} deviates from the computed checksum #{checksum_computed}." if checksum_extracted != checksum_computed
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,545 @@
|
|
1
|
+
# Copyright 2011 Christoffer Lervag
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
#
|
16
|
+
module RTP
|
17
|
+
|
18
|
+
# The Plan class is the highest level of objects in the RTPConnect hierarchy,
|
19
|
+
# and the one the user will interact with to read, modify and write files.
|
20
|
+
#
|
21
|
+
# === Relations
|
22
|
+
#
|
23
|
+
# * Parent: none
|
24
|
+
# * Children: Prescription, DoseTracking
|
25
|
+
#
|
26
|
+
class Plan < Record
|
27
|
+
include Logging
|
28
|
+
|
29
|
+
# The Record which this instance belongs to (nil by definition)
|
30
|
+
attr_reader :parent
|
31
|
+
# An array of Prescription records (if any) that belongs to this Plan.
|
32
|
+
attr_reader :prescriptions
|
33
|
+
# An array of DoseTracking records (if any) that belongs to this Plan.
|
34
|
+
attr_reader :dose_trackings
|
35
|
+
attr_reader :patient_id
|
36
|
+
attr_reader :patient_last_name
|
37
|
+
attr_reader :patient_first_name
|
38
|
+
attr_reader :patient_middle_initial
|
39
|
+
attr_reader :plan_id
|
40
|
+
attr_reader :plan_date
|
41
|
+
attr_reader :plan_time
|
42
|
+
attr_reader :course_id
|
43
|
+
attr_reader :diagnosis
|
44
|
+
attr_reader :md_last_name
|
45
|
+
attr_reader :md_first_name
|
46
|
+
attr_reader :md_middle_initial
|
47
|
+
attr_reader :md_approve_last_name
|
48
|
+
attr_reader :md_approve_first_name
|
49
|
+
attr_reader :md_approve_middle_initial
|
50
|
+
attr_reader :phy_approve_last_name
|
51
|
+
attr_reader :phy_approve_first_name
|
52
|
+
attr_reader :phy_approve_middle_initial
|
53
|
+
attr_reader :author_last_name
|
54
|
+
attr_reader :author_first_name
|
55
|
+
attr_reader :author_middle_initial
|
56
|
+
attr_reader :rtp_mfg
|
57
|
+
attr_reader :rtp_model
|
58
|
+
attr_reader :rtp_version
|
59
|
+
attr_reader :rtp_if_protocol
|
60
|
+
attr_reader :rtp_if_version
|
61
|
+
|
62
|
+
# Creates a new Plan by loading a plan definition string (i.e. a single line).
|
63
|
+
#
|
64
|
+
# === Notes
|
65
|
+
#
|
66
|
+
# * This method does not perform crc verification on the given string.
|
67
|
+
# * If such verification is desired, use methods ::parse or ::read instead.
|
68
|
+
#
|
69
|
+
# === Parameters
|
70
|
+
#
|
71
|
+
# * <tt>string</tt> -- A string containing a plan definition record.
|
72
|
+
#
|
73
|
+
def self.load(string)
|
74
|
+
raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
|
75
|
+
# Get the quote-less values:
|
76
|
+
values = string.values
|
77
|
+
raise ArgumentError, "Invalid argument 'string': Expected exactly 28 elements, got #{values.length}." unless values.length == 28
|
78
|
+
rtp = self.new
|
79
|
+
# Assign the values to attributes:
|
80
|
+
rtp.keyword = values[0]
|
81
|
+
rtp.patient_id = values[1]
|
82
|
+
rtp.patient_last_name = values[2]
|
83
|
+
rtp.patient_first_name = values[3]
|
84
|
+
rtp.patient_middle_initial = values[4]
|
85
|
+
rtp.plan_id = values[5]
|
86
|
+
rtp.plan_date = values[6]
|
87
|
+
rtp.plan_time = values[7]
|
88
|
+
rtp.course_id = values[8]
|
89
|
+
rtp.diagnosis = values[9]
|
90
|
+
rtp.md_last_name = values[10]
|
91
|
+
rtp.md_first_name = values[11]
|
92
|
+
rtp.md_middle_initial = values[12]
|
93
|
+
rtp.md_approve_last_name = values[13]
|
94
|
+
rtp.md_approve_first_name = values[14]
|
95
|
+
rtp.md_approve_middle_initial = values[15]
|
96
|
+
rtp.phy_approve_last_name = values[16]
|
97
|
+
rtp.phy_approve_first_name = values[17]
|
98
|
+
rtp.phy_approve_middle_initial = values[18]
|
99
|
+
rtp.author_last_name = values[19]
|
100
|
+
rtp.author_first_name = values[20]
|
101
|
+
rtp.author_middle_initial = values[21]
|
102
|
+
rtp.rtp_mfg = values[22]
|
103
|
+
rtp.rtp_model = values[23]
|
104
|
+
rtp.rtp_version = values[24]
|
105
|
+
rtp.rtp_if_protocol = values[25]
|
106
|
+
rtp.rtp_if_version = values[26]
|
107
|
+
rtp.crc = values[27]
|
108
|
+
return rtp
|
109
|
+
end
|
110
|
+
|
111
|
+
# Creates an RTP::Plan instance by parsing a RTPConnect string
|
112
|
+
# (i.e. multiple lines, containing multiple definitions).
|
113
|
+
#
|
114
|
+
# === Parameters
|
115
|
+
#
|
116
|
+
# * <tt>string</tt> -- An RTPConnect ascii string.
|
117
|
+
#
|
118
|
+
def self.parse(string)
|
119
|
+
raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
|
120
|
+
raise ArgumentError, "Invalid argument 'string': String too short to contain valid RTP data (length: #{string.length})." if string.length < 10
|
121
|
+
#lines = string.lines
|
122
|
+
lines = string.split("\r\n")
|
123
|
+
# Create the Plan object:
|
124
|
+
line = lines.first
|
125
|
+
RTP::verify(line)
|
126
|
+
rtp = self.load(line)
|
127
|
+
lines[1..-1].each do |line|
|
128
|
+
# Validate, determine type, and process the line accordingly to
|
129
|
+
# build the hierarchy of records:
|
130
|
+
RTP::verify(line)
|
131
|
+
values = line.values
|
132
|
+
keyword = values.first
|
133
|
+
method = RTP::PARSE_METHOD[keyword]
|
134
|
+
raise ArgumentError, "Unknown keyword #{keyword} extracted from string." unless method
|
135
|
+
rtp.send(method, line)
|
136
|
+
end
|
137
|
+
return rtp
|
138
|
+
end
|
139
|
+
|
140
|
+
# Creates an RTP::Plan instance by reading and parsing an RTPConnect file.
|
141
|
+
#
|
142
|
+
# === Parameters
|
143
|
+
#
|
144
|
+
# * <tt>file</tt> -- A string which specifies the path of the RTPConnect file to be loaded.
|
145
|
+
#
|
146
|
+
def self.read(file)
|
147
|
+
raise ArgumentError, "Invalid argument 'file'. Expected String, got #{file.class}." unless file.is_a?(String)
|
148
|
+
# Read the file content:
|
149
|
+
str = nil
|
150
|
+
unless File.exist?(file)
|
151
|
+
logger.error("Invalid (non-existing) file: #{file}")
|
152
|
+
else
|
153
|
+
unless File.readable?(file)
|
154
|
+
logger.error("File exists but I don't have permission to read it: #{file}")
|
155
|
+
else
|
156
|
+
if File.directory?(file)
|
157
|
+
logger.error("Expected a file, got a directory: #{file}")
|
158
|
+
else
|
159
|
+
if File.size(file) < 10
|
160
|
+
logger.error("This file is too small to contain valid RTP information: #{file}.")
|
161
|
+
else
|
162
|
+
str = File.open(file, "rb") { |f| f.read }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
# Parse the file contents and create the RTP::Connect object:
|
168
|
+
if str
|
169
|
+
rtp = self.parse(str)
|
170
|
+
else
|
171
|
+
raise "An RTP::Plan object could not be created from the specified file. Check the log for more details."
|
172
|
+
end
|
173
|
+
return rtp
|
174
|
+
end
|
175
|
+
|
176
|
+
# Creates a new Plan.
|
177
|
+
#
|
178
|
+
def initialize
|
179
|
+
@current_parent = self
|
180
|
+
# Child records:
|
181
|
+
@prescriptions = Array.new
|
182
|
+
@dose_trackings = Array.new
|
183
|
+
# No parent (by definition) for the Plan record:
|
184
|
+
@parent = nil
|
185
|
+
@keyword = 'PLAN_DEF'
|
186
|
+
end
|
187
|
+
|
188
|
+
# Adds a prescription site record to this instance.
|
189
|
+
#
|
190
|
+
def add_prescription(child)
|
191
|
+
raise ArgumentError, "Invalid argument 'child'. Expected RTP::Prescription, got #{child.class}." unless child.is_a?(RTP::Prescription)
|
192
|
+
@prescriptions << child
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the a properly sorted array of the child records of this instance.
|
196
|
+
#
|
197
|
+
def children
|
198
|
+
return [@prescriptions, @dose_trackings].flatten.compact
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns the values of this instance in an array.
|
202
|
+
# The values does not include the CRC.
|
203
|
+
#
|
204
|
+
def values
|
205
|
+
return [
|
206
|
+
@keyword,
|
207
|
+
@patient_id,
|
208
|
+
@patient_last_name,
|
209
|
+
@patient_first_name,
|
210
|
+
@patient_middle_initial,
|
211
|
+
@plan_id,
|
212
|
+
@plan_date,
|
213
|
+
@plan_time,
|
214
|
+
@course_id,
|
215
|
+
@diagnosis,
|
216
|
+
@md_last_name,
|
217
|
+
@md_first_name,
|
218
|
+
@md_middle_initial,
|
219
|
+
@md_approve_last_name,
|
220
|
+
@md_approve_first_name,
|
221
|
+
@md_approve_middle_initial,
|
222
|
+
@phy_approve_last_name,
|
223
|
+
@phy_approve_first_name,
|
224
|
+
@phy_approve_middle_initial,
|
225
|
+
@author_last_name,
|
226
|
+
@author_first_name,
|
227
|
+
@author_middle_initial,
|
228
|
+
@rtp_mfg,
|
229
|
+
@rtp_model,
|
230
|
+
@rtp_version,
|
231
|
+
@rtp_if_protocol,
|
232
|
+
@rtp_if_version
|
233
|
+
]
|
234
|
+
end
|
235
|
+
|
236
|
+
# Writes the Plan object + any hiearchy of child objects,
|
237
|
+
# to a properly formatted RTPConnect ascii string.
|
238
|
+
#
|
239
|
+
def to_str
|
240
|
+
str = encode #.force_encoding('utf-8')
|
241
|
+
children.each do |child|
|
242
|
+
str += child.to_str #.force_encoding('utf-8')
|
243
|
+
end
|
244
|
+
return str
|
245
|
+
end
|
246
|
+
|
247
|
+
# Writes the Plan object, along with its hiearchy of child objects,
|
248
|
+
# to a properly formatted RTPConnect ascii file.
|
249
|
+
#
|
250
|
+
# === Parameters
|
251
|
+
#
|
252
|
+
# * <tt>file</tt> -- A path/file string.
|
253
|
+
#
|
254
|
+
def write(file)
|
255
|
+
f = open_file(file)
|
256
|
+
f.write(to_str)
|
257
|
+
f.close
|
258
|
+
end
|
259
|
+
|
260
|
+
# Sets the keyword attribute.
|
261
|
+
#
|
262
|
+
def keyword=(value)
|
263
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
264
|
+
raise ArgumentError, "Invalid keyword. Expected 'PLAN_DEF', got #{value}." unless value.upcase == "PLAN_DEF"
|
265
|
+
@keyword = value
|
266
|
+
end
|
267
|
+
|
268
|
+
# Sets the patient_id attribute.
|
269
|
+
#
|
270
|
+
def patient_id=(value)
|
271
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
272
|
+
@patient_id = value
|
273
|
+
end
|
274
|
+
|
275
|
+
# Sets the patient_last_name attribute.
|
276
|
+
#
|
277
|
+
def patient_last_name=(value)
|
278
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
279
|
+
@patient_last_name = value
|
280
|
+
end
|
281
|
+
|
282
|
+
# Sets the patient_first_name attribute.
|
283
|
+
#
|
284
|
+
def patient_first_name=(value)
|
285
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
286
|
+
@patient_first_name = value
|
287
|
+
end
|
288
|
+
|
289
|
+
# Sets the patient_middle_initial attribute.
|
290
|
+
#
|
291
|
+
def patient_middle_initial=(value)
|
292
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
293
|
+
@patient_middle_initial = value
|
294
|
+
end
|
295
|
+
|
296
|
+
# Sets the plan_id attribute.
|
297
|
+
#
|
298
|
+
def plan_id=(value)
|
299
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
300
|
+
@plan_id = value
|
301
|
+
end
|
302
|
+
|
303
|
+
# Sets the plan_date attribute.
|
304
|
+
#
|
305
|
+
def plan_date=(value)
|
306
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
307
|
+
@plan_date = value
|
308
|
+
end
|
309
|
+
|
310
|
+
# Sets the plan_time attribute.
|
311
|
+
#
|
312
|
+
def plan_time=(value)
|
313
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
314
|
+
@plan_time = value
|
315
|
+
end
|
316
|
+
|
317
|
+
# Sets the course_id attribute.
|
318
|
+
#
|
319
|
+
def course_id=(value)
|
320
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
321
|
+
@course_id = value
|
322
|
+
end
|
323
|
+
|
324
|
+
# Sets the diagnosis attribute.
|
325
|
+
#
|
326
|
+
def diagnosis=(value)
|
327
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
328
|
+
@diagnosis = value
|
329
|
+
end
|
330
|
+
|
331
|
+
# Sets the md_last_name attribute.
|
332
|
+
#
|
333
|
+
def md_last_name=(value)
|
334
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
335
|
+
@md_last_name = value
|
336
|
+
end
|
337
|
+
|
338
|
+
# Sets the md_first_name attribute.
|
339
|
+
#
|
340
|
+
def md_first_name=(value)
|
341
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
342
|
+
@md_first_name = value
|
343
|
+
end
|
344
|
+
|
345
|
+
# Sets the md_middle_initial attribute.
|
346
|
+
#
|
347
|
+
def md_middle_initial=(value)
|
348
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
349
|
+
@md_middle_initial = value
|
350
|
+
end
|
351
|
+
|
352
|
+
# Sets the md_approve_last_name attribute.
|
353
|
+
#
|
354
|
+
def md_approve_last_name=(value)
|
355
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
356
|
+
@md_approve_last_name = value
|
357
|
+
end
|
358
|
+
|
359
|
+
# Sets the md_approve_first_name attribute.
|
360
|
+
#
|
361
|
+
def md_approve_first_name=(value)
|
362
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
363
|
+
@md_approve_first_name = value
|
364
|
+
end
|
365
|
+
|
366
|
+
# Sets the md_approve_middle_initial attribute.
|
367
|
+
#
|
368
|
+
def md_approve_middle_initial=(value)
|
369
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
370
|
+
@md_approve_middle_initial = value
|
371
|
+
end
|
372
|
+
|
373
|
+
# Sets the phy_approve_last_name attribute.
|
374
|
+
#
|
375
|
+
def phy_approve_last_name=(value)
|
376
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
377
|
+
@phy_approve_last_name = value
|
378
|
+
end
|
379
|
+
|
380
|
+
# Sets the phy_approve_first_name attribute.
|
381
|
+
#
|
382
|
+
def phy_approve_first_name=(value)
|
383
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
384
|
+
@phy_approve_first_name = value
|
385
|
+
end
|
386
|
+
|
387
|
+
# Sets the phy_approve_middle_initial attribute.
|
388
|
+
#
|
389
|
+
def phy_approve_middle_initial=(value)
|
390
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
391
|
+
@phy_approve_middle_initial = value
|
392
|
+
end
|
393
|
+
|
394
|
+
# Sets the author_last_name attribute.
|
395
|
+
#
|
396
|
+
def author_last_name=(value)
|
397
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
398
|
+
@author_last_name = value
|
399
|
+
end
|
400
|
+
|
401
|
+
# Sets the author_first_name attribute.
|
402
|
+
#
|
403
|
+
def author_first_name=(value)
|
404
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
405
|
+
@author_first_name = value
|
406
|
+
end
|
407
|
+
|
408
|
+
# Sets the author_middle_initial attribute.
|
409
|
+
#
|
410
|
+
def author_middle_initial=(value)
|
411
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
412
|
+
@author_middle_initial = value
|
413
|
+
end
|
414
|
+
|
415
|
+
# Sets the rtp_mfg attribute.
|
416
|
+
#
|
417
|
+
def rtp_mfg=(value)
|
418
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
419
|
+
@rtp_mfg = value
|
420
|
+
end
|
421
|
+
|
422
|
+
# Sets the rtp_model attribute.
|
423
|
+
#
|
424
|
+
def rtp_model=(value)
|
425
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
426
|
+
@rtp_model = value
|
427
|
+
end
|
428
|
+
|
429
|
+
# Sets the rtp_version attribute.
|
430
|
+
#
|
431
|
+
def rtp_version=(value)
|
432
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
433
|
+
@rtp_version = value
|
434
|
+
end
|
435
|
+
|
436
|
+
# Sets the rtp_if_protocol attribute.
|
437
|
+
#
|
438
|
+
def rtp_if_protocol=(value)
|
439
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
440
|
+
@rtp_if_protocol = value
|
441
|
+
end
|
442
|
+
|
443
|
+
# Sets the rtp_if_version attribute.
|
444
|
+
#
|
445
|
+
def rtp_if_version=(value)
|
446
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
447
|
+
@rtp_if_version = value
|
448
|
+
end
|
449
|
+
|
450
|
+
|
451
|
+
private
|
452
|
+
|
453
|
+
|
454
|
+
# Creates a control point record from the given string.
|
455
|
+
#
|
456
|
+
# === Parameters
|
457
|
+
#
|
458
|
+
# * <tt>string</tt> -- An single line string from an RTPConnect ascii file.
|
459
|
+
#
|
460
|
+
def control_point(string)
|
461
|
+
cp = ControlPoint.load(string, @current_parent)
|
462
|
+
@current_parent = cp
|
463
|
+
end
|
464
|
+
|
465
|
+
# Creates an extended treatment field record from the given string.
|
466
|
+
#
|
467
|
+
# === Parameters
|
468
|
+
#
|
469
|
+
# * <tt>string</tt> -- An single line string from an RTPConnect ascii file.
|
470
|
+
#
|
471
|
+
def extended_treatment_field(string)
|
472
|
+
ef = ExtendedField.load(string, @current_parent)
|
473
|
+
@current_parent = ef
|
474
|
+
end
|
475
|
+
|
476
|
+
# Tests if the path/file is writable, creates any folders if necessary, and opens the file for writing.
|
477
|
+
#
|
478
|
+
# === Parameters
|
479
|
+
#
|
480
|
+
# * <tt>file</tt> -- A path/file string.
|
481
|
+
#
|
482
|
+
def open_file(file)
|
483
|
+
# Check if file already exists:
|
484
|
+
if File.exist?(file)
|
485
|
+
# Is (the existing file) writable?
|
486
|
+
unless File.writable?(file)
|
487
|
+
#logger.error("The program does not have permission or resources to create this file: #{file}")
|
488
|
+
raise "The program does not have permission or resources to create this file: #{file}"
|
489
|
+
end
|
490
|
+
else
|
491
|
+
# File does not exist.
|
492
|
+
# Check if this file's path contains a folder that does not exist, and therefore needs to be created:
|
493
|
+
folders = file.split(File::SEPARATOR)
|
494
|
+
if folders.length > 1
|
495
|
+
# Remove last element (which should be the file string):
|
496
|
+
folders.pop
|
497
|
+
path = folders.join(File::SEPARATOR)
|
498
|
+
# Check if this path exists:
|
499
|
+
unless File.directory?(path)
|
500
|
+
# We need to create (parts of) this path:
|
501
|
+
require 'fileutils'
|
502
|
+
FileUtils.mkdir_p(path)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
# It has been verified that the file can be created:
|
507
|
+
return File.new(file, "wb")
|
508
|
+
end
|
509
|
+
|
510
|
+
# Creates a prescription site record from the given string.
|
511
|
+
#
|
512
|
+
# === Parameters
|
513
|
+
#
|
514
|
+
# * <tt>string</tt> -- An single line string from an RTPConnect ascii file.
|
515
|
+
#
|
516
|
+
def prescription_site(string)
|
517
|
+
p = Prescription.load(string, @current_parent)
|
518
|
+
@current_parent = p
|
519
|
+
end
|
520
|
+
|
521
|
+
# Creates a site setup record from the given string.
|
522
|
+
#
|
523
|
+
# === Parameters
|
524
|
+
#
|
525
|
+
# * <tt>string</tt> -- An single line string from an RTPConnect ascii file.
|
526
|
+
#
|
527
|
+
def site_setup(string)
|
528
|
+
s = SiteSetup.load(string, @current_parent)
|
529
|
+
@current_parent = s
|
530
|
+
end
|
531
|
+
|
532
|
+
# Creates a treatment field record from the given string.
|
533
|
+
#
|
534
|
+
# === Parameters
|
535
|
+
#
|
536
|
+
# * <tt>string</tt> -- An single line string from an RTPConnect ascii file.
|
537
|
+
#
|
538
|
+
def treatment_field(string)
|
539
|
+
f = Field.load(string, @current_parent)
|
540
|
+
@current_parent = f
|
541
|
+
end
|
542
|
+
|
543
|
+
end
|
544
|
+
|
545
|
+
end
|