pantheios-ruby 0.9.6
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.
- checksums.yaml +7 -0
- data/lib/pantheios.rb +39 -0
- data/lib/pantheios/api.rb +275 -0
- data/lib/pantheios/application_layer.rb +20 -0
- data/lib/pantheios/application_layer/param_name_list.rb +13 -0
- data/lib/pantheios/application_layer/stock_severity_levels.rb +146 -0
- data/lib/pantheios/core.rb +446 -0
- data/lib/pantheios/globals.rb +109 -0
- data/lib/pantheios/services/simple_console_service.rb +20 -0
- data/lib/pantheios/util.rb +5 -0
- data/lib/pantheios/util/process_util.rb +22 -0
- data/lib/pantheios/util/thread_util.rb +83 -0
- data/lib/pantheios/util/version_util.rb +44 -0
- data/lib/pantheios/version.rb +69 -0
- data/test/unit/application_layer/tc_param_name_list.rb +35 -0
- data/test/unit/application_layer/tc_stock_severity_levels.rb +103 -0
- data/test/unit/application_layer/ts_all.rb +12 -0
- data/test/unit/ts_all.rb +12 -0
- data/test/unit/util/tc_thread_util.rb +100 -0
- data/test/unit/util/tc_version_util.rb +80 -0
- data/test/unit/util/ts_all.rb +12 -0
- metadata +85 -0
@@ -0,0 +1,446 @@
|
|
1
|
+
|
2
|
+
# ######################################################################## #
|
3
|
+
# File: lib/pantheios/core.rb
|
4
|
+
#
|
5
|
+
# Purpose: The Pantheios.Ruby core (::Pantheios::Core)
|
6
|
+
#
|
7
|
+
# Created: 2nd April 2011
|
8
|
+
# Updated: 25th December 2017
|
9
|
+
#
|
10
|
+
# Home: http://github.com/synesissoftware/Pantheios-Ruby
|
11
|
+
#
|
12
|
+
# Author: Matthew Wilson
|
13
|
+
#
|
14
|
+
# Copyright (c) 2011-2017, Matthew Wilson and Synesis Software
|
15
|
+
# All rights reserved.
|
16
|
+
#
|
17
|
+
# Redistribution and use in source and binary forms, with or without
|
18
|
+
# modification, are permitted provided that the following conditions are
|
19
|
+
# met:
|
20
|
+
#
|
21
|
+
# * Redistributions of source code must retain the above copyright
|
22
|
+
# notice, this list of conditions and the following disclaimer.
|
23
|
+
#
|
24
|
+
# * Redistributions in binary form must reproduce the above copyright
|
25
|
+
# notice, this list of conditions and the following disclaimer in the
|
26
|
+
# documentation and/or other materials provided with the distribution.
|
27
|
+
#
|
28
|
+
# * Neither the names of the copyright holder nor the names of its
|
29
|
+
# contributors may be used to endorse or promote products derived from
|
30
|
+
# this software without specific prior written permission.
|
31
|
+
#
|
32
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
33
|
+
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
34
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
35
|
+
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
36
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
37
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
38
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
39
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
40
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
41
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
42
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
43
|
+
#
|
44
|
+
# ######################################################################## #
|
45
|
+
|
46
|
+
|
47
|
+
require 'pantheios/globals'
|
48
|
+
|
49
|
+
require 'pantheios/application_layer/stock_severity_levels'
|
50
|
+
require 'pantheios/util/process_util'
|
51
|
+
|
52
|
+
require 'pantheios/services/simple_console_service'
|
53
|
+
|
54
|
+
=begin
|
55
|
+
=end
|
56
|
+
|
57
|
+
module Pantheios
|
58
|
+
module Core
|
59
|
+
|
60
|
+
module Constants_
|
61
|
+
|
62
|
+
REQUIRED_SERVICE_METHODS = %w{ severity_logged? log }.map { |name| name.to_sym }
|
63
|
+
REQUIRED_FRONTEND_METHODS = %w{ severity_logged? }.map { |name| name.to_sym }
|
64
|
+
REQUIRED_BACKEND_METHODS = %w{ log }.map { |name| name.to_sym }
|
65
|
+
|
66
|
+
end # module Constants_
|
67
|
+
|
68
|
+
module Internals_
|
69
|
+
|
70
|
+
class DefaultDiscriminator
|
71
|
+
|
72
|
+
def severity_logged? severity
|
73
|
+
|
74
|
+
return true if $DEBUG
|
75
|
+
|
76
|
+
levels = ::Pantheios::ApplicationLayer::StockSeverityLevels::STOCK_SEVERITY_LEVEL_VALUES
|
77
|
+
|
78
|
+
v_info = levels[:informational]
|
79
|
+
v_sev = levels[severity] if ::Symbol === severity
|
80
|
+
|
81
|
+
return false if v_sev > v_info
|
82
|
+
|
83
|
+
true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# :nodoc:
|
88
|
+
class State
|
89
|
+
|
90
|
+
def initialize default_fe
|
91
|
+
|
92
|
+
@mx_service = Mutex.new
|
93
|
+
@front_end = nil
|
94
|
+
@back_end = nil
|
95
|
+
@requires_prefix = false;
|
96
|
+
@default_fe = default_fe
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_front_end fe
|
100
|
+
|
101
|
+
raise ::TypeError, "front-end instance (#{fe.class}) does not respond to all the required messages (#{Constants_::REQUIRED_FRONTEND_METHODS.join(', ')})" unless fe && Constants_::REQUIRED_FRONTEND_METHODS.all? { |m| fe.respond_to? m }
|
102
|
+
|
103
|
+
r = nil
|
104
|
+
|
105
|
+
fe ||= @default_fe
|
106
|
+
|
107
|
+
@mx_service.synchronize do
|
108
|
+
|
109
|
+
r, @front_end = @front_end, fe
|
110
|
+
end
|
111
|
+
|
112
|
+
r = nil if r.object_id == @default_fe.object_id
|
113
|
+
|
114
|
+
return r
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_back_end be
|
118
|
+
|
119
|
+
raise ::TypeError, "back-end instance (#{fe.class}) does not respond to all the required messages (#{Constants_::REQUIRED_BACKEND_METHODS.join(', ')})" unless be && Constants_::REQUIRED_BACKEND_METHODS.all? { |m| be.respond_to? m }
|
120
|
+
|
121
|
+
r = nil
|
122
|
+
srp = svc.respond_to?(:requires_prefix?) ? svc.requires_prefix? : true
|
123
|
+
|
124
|
+
@mx_service.synchronize do
|
125
|
+
|
126
|
+
r, @back_end, @requires_prefix = @back_end, be, srp
|
127
|
+
end
|
128
|
+
|
129
|
+
return r
|
130
|
+
end
|
131
|
+
|
132
|
+
def set_service svc
|
133
|
+
|
134
|
+
raise ::TypeError, "service instance (#{svc.class}) does not respond to all the required messages (#{Constants_::REQUIRED_SERVICE_METHODS.join(', ')})" unless svc && Constants_::REQUIRED_SERVICE_METHODS.all? { |m| svc.respond_to? m }
|
135
|
+
|
136
|
+
r = []
|
137
|
+
srp = svc.respond_to?(:requires_prefix?) ? svc.requires_prefix? : true
|
138
|
+
|
139
|
+
@mx_service.synchronize do
|
140
|
+
|
141
|
+
r << @front_end
|
142
|
+
r << @back_end
|
143
|
+
|
144
|
+
@front_end, @back_end, @requires_prefix = svc, svc, srp
|
145
|
+
end
|
146
|
+
|
147
|
+
return r
|
148
|
+
end
|
149
|
+
|
150
|
+
def severity_logged? severity
|
151
|
+
|
152
|
+
@mx_service.synchronize do
|
153
|
+
|
154
|
+
return nil unless @front_end
|
155
|
+
|
156
|
+
@front_end.severity_logged? severity
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def log
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
def discriminator
|
165
|
+
|
166
|
+
@mx_service.synchronize do
|
167
|
+
|
168
|
+
if @service && @service.respond_to?(:severity_logged?)
|
169
|
+
|
170
|
+
return @service
|
171
|
+
end
|
172
|
+
|
173
|
+
@front_end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
attr_reader :service
|
178
|
+
attr_reader :front_end
|
179
|
+
attr_reader :back_end
|
180
|
+
def requires_prefix?; @requires_prefix; end
|
181
|
+
end
|
182
|
+
end # module Internals_
|
183
|
+
|
184
|
+
def self.included receiver
|
185
|
+
|
186
|
+
abort "Attempt to include #{self} into #{receiver}. This is not allowed"
|
187
|
+
end
|
188
|
+
|
189
|
+
# :nodoc:
|
190
|
+
def self.core_init
|
191
|
+
|
192
|
+
@@state = Internals_::State.new Internals_::DefaultDiscriminator.new
|
193
|
+
|
194
|
+
self.set_default_service
|
195
|
+
end
|
196
|
+
|
197
|
+
# :nodoc:
|
198
|
+
def self.set_default_service **options
|
199
|
+
|
200
|
+
# determine which log service to initialise as the default
|
201
|
+
|
202
|
+
(::Pantheios::Globals.INITIAL_SERVICE_INSTANCES || []).each do |inst|
|
203
|
+
|
204
|
+
next unless inst
|
205
|
+
|
206
|
+
return @@state.set_service inst
|
207
|
+
end
|
208
|
+
|
209
|
+
(::Pantheios::Globals.INITIAL_SERVICE_CLASSES || []).each do |cls|
|
210
|
+
|
211
|
+
inst = cls.new
|
212
|
+
|
213
|
+
return @@state.set_service inst
|
214
|
+
end
|
215
|
+
|
216
|
+
@@state.set_service ::Pantheios::Services::SimpleConsoleService.new
|
217
|
+
end
|
218
|
+
|
219
|
+
# Sets the front-end that will be used to evaluate whether a given log
|
220
|
+
# statement will be logged
|
221
|
+
#
|
222
|
+
# * *Parameters:*
|
223
|
+
# - +fe+ The front-end instance. It must respond to the
|
224
|
+
# +severity_logged?+ message, or a ::TypeError will be raised
|
225
|
+
#
|
226
|
+
# * *Returns:*
|
227
|
+
# The previously registered instance, or +nil+ if no previous one was
|
228
|
+
# registered
|
229
|
+
def self.set_front_end fe
|
230
|
+
|
231
|
+
@@state.set_front_end fe
|
232
|
+
end
|
233
|
+
|
234
|
+
# Sets the back-end used to emit the given log statement
|
235
|
+
#
|
236
|
+
# * *Parameters:*
|
237
|
+
# - +be+ The back-end instance. It must respond to the
|
238
|
+
# +log+ message, or a ::TypeError will be raised. It may also respond
|
239
|
+
# to the +requires_prefix?+ message, which can be used to indicate
|
240
|
+
# whether a prepared prefix is required; if not present, the
|
241
|
+
# framework assumes that the back-end requires a prefix
|
242
|
+
#
|
243
|
+
# * *Returns:*
|
244
|
+
# The previously registered instance, or +nil+ if no previous one was
|
245
|
+
# registered
|
246
|
+
def self.set_back_end be
|
247
|
+
|
248
|
+
@@state.set_back_end be
|
249
|
+
end
|
250
|
+
|
251
|
+
# Sets the service that will be used to evaluate whether a given log
|
252
|
+
# statement will be logged and to emit it
|
253
|
+
#
|
254
|
+
# * *Parameters:*
|
255
|
+
# - +svc+ The service instance. It must respond to the
|
256
|
+
# +severity_logged?+ and +log+ messages, or a ::TypeError will be
|
257
|
+
# raised. It may also respond to the +requires_prefix?+ message,
|
258
|
+
# which can be used to indicate whether a prepared prefix is
|
259
|
+
# required; if not present, the framework assumes that the service
|
260
|
+
# (back-end) requires a prefix
|
261
|
+
#
|
262
|
+
# * *Returns:*
|
263
|
+
# An array of two elements, representing the previous front-end and
|
264
|
+
# previous back-end
|
265
|
+
def self.set_service svc
|
266
|
+
|
267
|
+
@@state.set_service svc
|
268
|
+
end
|
269
|
+
|
270
|
+
self.core_init
|
271
|
+
|
272
|
+
# :nodoc:
|
273
|
+
def self.register_include includee, includer
|
274
|
+
|
275
|
+
$stderr.puts "#{includee} included into #{includer}" if $DEBUG
|
276
|
+
end
|
277
|
+
|
278
|
+
# Default implementation to determine whether the given severity is
|
279
|
+
# logged
|
280
|
+
#
|
281
|
+
# * *Returns:*
|
282
|
+
# If +$DEBUG+ is +true+, then returns +true+ - all statements are
|
283
|
+
# emitted in debug mode. In normal operation, if the integral value of
|
284
|
+
# +severity+ is greater than that of +:informational+ then it returns
|
285
|
+
# +false+; otherwise it return +true+
|
286
|
+
def self.severity_logged? severity
|
287
|
+
|
288
|
+
@@state.severity_logged? severity
|
289
|
+
end
|
290
|
+
|
291
|
+
# Default implementation to obtain the process id
|
292
|
+
#
|
293
|
+
# * *Returns:*
|
294
|
+
# +Process.pid+
|
295
|
+
def self.process_id
|
296
|
+
|
297
|
+
Process.pid
|
298
|
+
end
|
299
|
+
|
300
|
+
# Default implementation to obtain the program name
|
301
|
+
#
|
302
|
+
# * *Returns:*
|
303
|
+
# The file stem of +$0+
|
304
|
+
#
|
305
|
+
# NOTE: this is implemented in terms of Process_Util.derive_process_name
|
306
|
+
# and the result is cached
|
307
|
+
def self.program_name
|
308
|
+
|
309
|
+
@program_name ||= ::Pantheios::Util::ProcessUtil.derive_process_name $0
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.severity_string severity
|
313
|
+
|
314
|
+
r = ApplicationLayer::StockSeverityLevels::STOCK_SEVERITY_LEVEL_STRINGS[severity] and return r
|
315
|
+
|
316
|
+
severity.to_s
|
317
|
+
end
|
318
|
+
|
319
|
+
# Default implementation to obtain the thread_id
|
320
|
+
#
|
321
|
+
# * *Returns:*
|
322
|
+
# From the current thread either the value obtained via the attribute
|
323
|
+
# +thread_name+ (if it responds to that) or via +object_id+
|
324
|
+
def self.thread_id
|
325
|
+
|
326
|
+
t = Thread.current
|
327
|
+
|
328
|
+
return t.thread_name if t.respond_to? :thread_name
|
329
|
+
|
330
|
+
t.object_id
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.timestamp_format
|
334
|
+
|
335
|
+
'%Y-%m-%d %H:%M:%S.%6N'
|
336
|
+
end
|
337
|
+
|
338
|
+
# Default implementation to obtain the timestamp according to a given
|
339
|
+
# format
|
340
|
+
#
|
341
|
+
# * *Parameters:*
|
342
|
+
# - +t+ [::Time] The time
|
343
|
+
# - +fmt+ [::String, nil] The format to be used. If +nil+ the value
|
344
|
+
# obtained by +timestamp_format+ is used
|
345
|
+
#
|
346
|
+
# * *Returns:*
|
347
|
+
# A string representing the time
|
348
|
+
def self.timestamp t, fmt
|
349
|
+
|
350
|
+
fmt ||= self.timestamp_format
|
351
|
+
|
352
|
+
t.strftime fmt
|
353
|
+
end
|
354
|
+
|
355
|
+
|
356
|
+
# Internal implementation method, not to be called by application code
|
357
|
+
def self.trace_v_prep prefix_provider, call_depth, argv
|
358
|
+
|
359
|
+
if ApplicationLayer::ParamNameList === argv[0]
|
360
|
+
|
361
|
+
self.trace_v_impl prefix_provider, 1 + call_depth, argv[0], :trace, argv[1..-1]
|
362
|
+
else
|
363
|
+
|
364
|
+
self.trace_v_impl prefix_provider, 1 + call_depth, nil, :trace, argv
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# Internal implementation method, not to be called by application code
|
369
|
+
def self.trace_v_impl prefix_provider, call_depth, param_list, severity, argv
|
370
|
+
|
371
|
+
case param_list
|
372
|
+
when nil
|
373
|
+
;
|
374
|
+
when ApplicationLayer::ParamNameList
|
375
|
+
;
|
376
|
+
else
|
377
|
+
|
378
|
+
warn "param_list (#{param_list.class}) must be nil or an instance of #{ApplicationLayer::ParamNameList}" unless param_list
|
379
|
+
end
|
380
|
+
|
381
|
+
fl = nil
|
382
|
+
rx = nil
|
383
|
+
fn = caller(call_depth + 1, 1)[0]
|
384
|
+
|
385
|
+
if ::Class === prefix_provider
|
386
|
+
|
387
|
+
rx = "#{prefix_provider}::"
|
388
|
+
else
|
389
|
+
|
390
|
+
rx = "#{prefix_provider.class}#"
|
391
|
+
end
|
392
|
+
|
393
|
+
if false;
|
394
|
+
elsif fn =~ /(.+)\:in\s*\`(.+)\'\s*$/
|
395
|
+
|
396
|
+
fl = $1
|
397
|
+
fn = $2
|
398
|
+
|
399
|
+
f = "#{fl}: #{rx}#{fn}"
|
400
|
+
elsif fn =~ /.*in\s*\`(.+)\'\s*$/
|
401
|
+
|
402
|
+
f = $1
|
403
|
+
else
|
404
|
+
|
405
|
+
f = fn
|
406
|
+
end
|
407
|
+
|
408
|
+
if param_list
|
409
|
+
|
410
|
+
sig = ''
|
411
|
+
|
412
|
+
argv.each_with_index do |arg, index0|
|
413
|
+
|
414
|
+
n = param_list[index0]
|
415
|
+
|
416
|
+
s = arg.to_s
|
417
|
+
s = "'#{s}'" if s.index(/[,\s]/)
|
418
|
+
|
419
|
+
sig += ', ' unless sig.empty?
|
420
|
+
|
421
|
+
sig += n ? "#{n} (#{arg.class})=#{s}" : s
|
422
|
+
end
|
423
|
+
else
|
424
|
+
|
425
|
+
sig = argv.join(', ')
|
426
|
+
end
|
427
|
+
|
428
|
+
stmt = "#{f}(#{sig})"
|
429
|
+
|
430
|
+
self.log_raw prefix_provider, severity, stmt
|
431
|
+
end
|
432
|
+
|
433
|
+
# Internal implementation method, not to be called by application code
|
434
|
+
def self.log_raw prefix_provider, severity, message
|
435
|
+
|
436
|
+
now = Time.now
|
437
|
+
|
438
|
+
prf = @@state.requires_prefix? ? '[' + prefix_provider.prefix(now, severity) + ']: ' : nil
|
439
|
+
|
440
|
+
@@state.back_end.log severity, now, prf, message
|
441
|
+
end
|
442
|
+
|
443
|
+
end # Core
|
444
|
+
end # Pantheios
|
445
|
+
|
446
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
# ######################################################################## #
|
3
|
+
# File: lib/pantheios/globals.rb
|
4
|
+
#
|
5
|
+
# Purpose: The Pantheios.Ruby "globals" (::Pantheios::Globals)
|
6
|
+
#
|
7
|
+
# Created: 24th December 2017
|
8
|
+
# Updated: 24th December 2017
|
9
|
+
#
|
10
|
+
# Home: http://github.com/synesissoftware/Pantheios-Ruby
|
11
|
+
#
|
12
|
+
# Author: Matthew Wilson
|
13
|
+
#
|
14
|
+
# Copyright (c) 2017, Matthew Wilson and Synesis Software
|
15
|
+
# All rights reserved.
|
16
|
+
#
|
17
|
+
# Redistribution and use in source and binary forms, with or without
|
18
|
+
# modification, are permitted provided that the following conditions are
|
19
|
+
# met:
|
20
|
+
#
|
21
|
+
# * Redistributions of source code must retain the above copyright
|
22
|
+
# notice, this list of conditions and the following disclaimer.
|
23
|
+
#
|
24
|
+
# * Redistributions in binary form must reproduce the above copyright
|
25
|
+
# notice, this list of conditions and the following disclaimer in the
|
26
|
+
# documentation and/or other materials provided with the distribution.
|
27
|
+
#
|
28
|
+
# * Neither the names of the copyright holder nor the names of its
|
29
|
+
# contributors may be used to endorse or promote products derived from
|
30
|
+
# this software without specific prior written permission.
|
31
|
+
#
|
32
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
33
|
+
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
34
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
35
|
+
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
36
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
37
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
38
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
39
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
40
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
41
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
42
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
43
|
+
#
|
44
|
+
# ######################################################################## #
|
45
|
+
|
46
|
+
|
47
|
+
=begin
|
48
|
+
=end
|
49
|
+
|
50
|
+
module Pantheios
|
51
|
+
# A utility namespace for the sole purpose of defining "globals" - actually
|
52
|
+
# module constants' values and module attributes - that control the
|
53
|
+
# behaviour of Pantheios globally
|
54
|
+
#
|
55
|
+
# NOTE: The "globals" in this namespace are operative before
|
56
|
+
# +::Pantheios::Core+ and +::Pantheios::API+
|
57
|
+
module Globals
|
58
|
+
|
59
|
+
module Internals_
|
60
|
+
|
61
|
+
BOOLEAN_CLASSES = [ ::FalseClass, ::TrueClass ]
|
62
|
+
TRUTHY_CLASSES = BOOLEAN_CLASSES + [ ::NilClass ]
|
63
|
+
end
|
64
|
+
|
65
|
+
module Helpers_
|
66
|
+
|
67
|
+
def self.cattr receiver, name, types, initial_value
|
68
|
+
|
69
|
+
types = nil if !types.nil? && types.empty?
|
70
|
+
|
71
|
+
receiver.class_eval do
|
72
|
+
|
73
|
+
field_name = '@' + name
|
74
|
+
|
75
|
+
instance_variable_set field_name, initial_value
|
76
|
+
|
77
|
+
define_singleton_method(name) do
|
78
|
+
|
79
|
+
instance_variable_get field_name
|
80
|
+
end
|
81
|
+
|
82
|
+
define_singleton_method(name + '=') do |v|
|
83
|
+
|
84
|
+
if types
|
85
|
+
|
86
|
+
warn "Assigning to #{__method__} with argument of invalid type - #{v.class} given; one of #{types.join(', ')} required" unless types.any? { |c| c === v }
|
87
|
+
end
|
88
|
+
|
89
|
+
instance_variable_set field_name, v
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
Helpers_.cattr self, 'HAS_CASCADED_INCLUDES', Internals_::BOOLEAN_CLASSES, true
|
96
|
+
|
97
|
+
Helpers_.cattr self, 'INITIAL_SERVICE_INSTANCES', nil, nil
|
98
|
+
|
99
|
+
Helpers_.cattr self, 'INITIAL_SERVICE_CLASSES', nil, nil
|
100
|
+
|
101
|
+
def self.included receiver
|
102
|
+
|
103
|
+
abort "Attempt to include #{self} into #{receiver}. This is not allowed"
|
104
|
+
end
|
105
|
+
|
106
|
+
end # module Globals
|
107
|
+
end # module Pantheios
|
108
|
+
|
109
|
+
|