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