rtp-connect 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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