openhab-jrubyscripting 5.0.0.rc1

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.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/lib/openhab/core/actions.rb +163 -0
  3. data/lib/openhab/core/entity_lookup.rb +144 -0
  4. data/lib/openhab/core/events/abstract_event.rb +17 -0
  5. data/lib/openhab/core/events/item_channel_link.rb +36 -0
  6. data/lib/openhab/core/events/item_command_event.rb +78 -0
  7. data/lib/openhab/core/events/item_event.rb +22 -0
  8. data/lib/openhab/core/events/item_state_changed_event.rb +52 -0
  9. data/lib/openhab/core/events/item_state_event.rb +51 -0
  10. data/lib/openhab/core/events/thing.rb +29 -0
  11. data/lib/openhab/core/events/thing_status_info_event.rb +53 -0
  12. data/lib/openhab/core/events.rb +10 -0
  13. data/lib/openhab/core/items/accepted_data_types.rb +29 -0
  14. data/lib/openhab/core/items/color_item.rb +52 -0
  15. data/lib/openhab/core/items/contact_item.rb +52 -0
  16. data/lib/openhab/core/items/date_time_item.rb +58 -0
  17. data/lib/openhab/core/items/dimmer_item.rb +148 -0
  18. data/lib/openhab/core/items/generic_item.rb +344 -0
  19. data/lib/openhab/core/items/group_item.rb +174 -0
  20. data/lib/openhab/core/items/image_item.rb +109 -0
  21. data/lib/openhab/core/items/location_item.rb +34 -0
  22. data/lib/openhab/core/items/metadata/hash.rb +390 -0
  23. data/lib/openhab/core/items/metadata/namespace_hash.rb +469 -0
  24. data/lib/openhab/core/items/metadata.rb +11 -0
  25. data/lib/openhab/core/items/number_item.rb +62 -0
  26. data/lib/openhab/core/items/numeric_item.rb +22 -0
  27. data/lib/openhab/core/items/persistence.rb +327 -0
  28. data/lib/openhab/core/items/player_item.rb +66 -0
  29. data/lib/openhab/core/items/proxy.rb +59 -0
  30. data/lib/openhab/core/items/registry.rb +66 -0
  31. data/lib/openhab/core/items/rollershutter_item.rb +68 -0
  32. data/lib/openhab/core/items/semantics/enumerable.rb +152 -0
  33. data/lib/openhab/core/items/semantics.rb +476 -0
  34. data/lib/openhab/core/items/state_storage.rb +53 -0
  35. data/lib/openhab/core/items/string_item.rb +28 -0
  36. data/lib/openhab/core/items/switch_item.rb +78 -0
  37. data/lib/openhab/core/items.rb +114 -0
  38. data/lib/openhab/core/lazy_array.rb +52 -0
  39. data/lib/openhab/core/profile_factory.rb +118 -0
  40. data/lib/openhab/core/script_handling.rb +55 -0
  41. data/lib/openhab/core/things/channel.rb +48 -0
  42. data/lib/openhab/core/things/channel_uid.rb +51 -0
  43. data/lib/openhab/core/things/item_channel_link.rb +33 -0
  44. data/lib/openhab/core/things/profile_callback.rb +52 -0
  45. data/lib/openhab/core/things/proxy.rb +69 -0
  46. data/lib/openhab/core/things/registry.rb +46 -0
  47. data/lib/openhab/core/things/thing.rb +194 -0
  48. data/lib/openhab/core/things.rb +22 -0
  49. data/lib/openhab/core/timer.rb +128 -0
  50. data/lib/openhab/core/types/comparable_type.rb +23 -0
  51. data/lib/openhab/core/types/date_time_type.rb +259 -0
  52. data/lib/openhab/core/types/decimal_type.rb +192 -0
  53. data/lib/openhab/core/types/hsb_type.rb +183 -0
  54. data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
  55. data/lib/openhab/core/types/next_previous_type.rb +34 -0
  56. data/lib/openhab/core/types/numeric_type.rb +52 -0
  57. data/lib/openhab/core/types/on_off_type.rb +46 -0
  58. data/lib/openhab/core/types/open_closed_type.rb +41 -0
  59. data/lib/openhab/core/types/percent_type.rb +95 -0
  60. data/lib/openhab/core/types/play_pause_type.rb +38 -0
  61. data/lib/openhab/core/types/point_type.rb +117 -0
  62. data/lib/openhab/core/types/quantity_type.rb +327 -0
  63. data/lib/openhab/core/types/raw_type.rb +26 -0
  64. data/lib/openhab/core/types/refresh_type.rb +27 -0
  65. data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
  66. data/lib/openhab/core/types/stop_move_type.rb +34 -0
  67. data/lib/openhab/core/types/string_type.rb +76 -0
  68. data/lib/openhab/core/types/type.rb +117 -0
  69. data/lib/openhab/core/types/un_def_type.rb +38 -0
  70. data/lib/openhab/core/types/up_down_type.rb +50 -0
  71. data/lib/openhab/core/types.rb +69 -0
  72. data/lib/openhab/core/uid.rb +36 -0
  73. data/lib/openhab/core.rb +85 -0
  74. data/lib/openhab/core_ext/java/duration.rb +115 -0
  75. data/lib/openhab/core_ext/java/local_date.rb +93 -0
  76. data/lib/openhab/core_ext/java/local_time.rb +106 -0
  77. data/lib/openhab/core_ext/java/month.rb +59 -0
  78. data/lib/openhab/core_ext/java/month_day.rb +105 -0
  79. data/lib/openhab/core_ext/java/period.rb +103 -0
  80. data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
  81. data/lib/openhab/core_ext/java/time.rb +58 -0
  82. data/lib/openhab/core_ext/java/unit.rb +15 -0
  83. data/lib/openhab/core_ext/java/zoned_date_time.rb +116 -0
  84. data/lib/openhab/core_ext/ruby/array.rb +21 -0
  85. data/lib/openhab/core_ext/ruby/class.rb +15 -0
  86. data/lib/openhab/core_ext/ruby/date.rb +89 -0
  87. data/lib/openhab/core_ext/ruby/numeric.rb +190 -0
  88. data/lib/openhab/core_ext/ruby/range.rb +70 -0
  89. data/lib/openhab/core_ext/ruby/time.rb +104 -0
  90. data/lib/openhab/core_ext.rb +18 -0
  91. data/lib/openhab/dsl/events/watch_event.rb +18 -0
  92. data/lib/openhab/dsl/events.rb +9 -0
  93. data/lib/openhab/dsl/gems.rb +3 -0
  94. data/lib/openhab/dsl/items/builder.rb +618 -0
  95. data/lib/openhab/dsl/items/ensure.rb +93 -0
  96. data/lib/openhab/dsl/items/timed_command.rb +236 -0
  97. data/lib/openhab/dsl/rules/automation_rule.rb +308 -0
  98. data/lib/openhab/dsl/rules/builder.rb +1373 -0
  99. data/lib/openhab/dsl/rules/guard.rb +115 -0
  100. data/lib/openhab/dsl/rules/name_inference.rb +160 -0
  101. data/lib/openhab/dsl/rules/property.rb +76 -0
  102. data/lib/openhab/dsl/rules/rule_triggers.rb +96 -0
  103. data/lib/openhab/dsl/rules/terse.rb +63 -0
  104. data/lib/openhab/dsl/rules/triggers/changed.rb +169 -0
  105. data/lib/openhab/dsl/rules/triggers/channel.rb +57 -0
  106. data/lib/openhab/dsl/rules/triggers/command.rb +107 -0
  107. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +161 -0
  108. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +164 -0
  109. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +195 -0
  110. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +127 -0
  111. data/lib/openhab/dsl/rules/triggers/trigger.rb +56 -0
  112. data/lib/openhab/dsl/rules/triggers/updated.rb +130 -0
  113. data/lib/openhab/dsl/rules/triggers/watch/watch.rb +55 -0
  114. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +155 -0
  115. data/lib/openhab/dsl/rules/triggers.rb +12 -0
  116. data/lib/openhab/dsl/rules.rb +29 -0
  117. data/lib/openhab/dsl/script_handling.rb +55 -0
  118. data/lib/openhab/dsl/things/builder.rb +263 -0
  119. data/lib/openhab/dsl/thread_local.rb +48 -0
  120. data/lib/openhab/dsl/timer_manager.rb +191 -0
  121. data/lib/openhab/dsl/version.rb +9 -0
  122. data/lib/openhab/dsl.rb +686 -0
  123. data/lib/openhab/log.rb +348 -0
  124. data/lib/openhab/osgi.rb +70 -0
  125. data/lib/openhab/rspec/configuration.rb +56 -0
  126. data/lib/openhab/rspec/example_group.rb +90 -0
  127. data/lib/openhab/rspec/helpers.rb +439 -0
  128. data/lib/openhab/rspec/hooks.rb +93 -0
  129. data/lib/openhab/rspec/jruby.rb +46 -0
  130. data/lib/openhab/rspec/karaf.rb +811 -0
  131. data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
  132. data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
  133. data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
  134. data/lib/openhab/rspec/mocks/metadata_provider.rb +75 -0
  135. data/lib/openhab/rspec/mocks/persistence_service.rb +140 -0
  136. data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
  137. data/lib/openhab/rspec/mocks/synchronous_executor.rb +56 -0
  138. data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
  139. data/lib/openhab/rspec/mocks/timer.rb +95 -0
  140. data/lib/openhab/rspec/openhab/core/actions.rb +26 -0
  141. data/lib/openhab/rspec/openhab/core/items/proxy.rb +27 -0
  142. data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
  143. data/lib/openhab/rspec/shell.rb +31 -0
  144. data/lib/openhab/rspec/suspend_rules.rb +60 -0
  145. data/lib/openhab/rspec.rb +17 -0
  146. data/lib/openhab/yard/cli/stats.rb +23 -0
  147. data/lib/openhab/yard/code_objects/group_object.rb +17 -0
  148. data/lib/openhab/yard/code_objects/java/base.rb +31 -0
  149. data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
  150. data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
  151. data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
  152. data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
  153. data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
  154. data/lib/openhab/yard/handlers/jruby/base.rb +49 -0
  155. data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
  156. data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
  157. data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +27 -0
  158. data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
  159. data/lib/openhab/yard/html_helper.rb +44 -0
  160. data/lib/openhab/yard/tags/constant_directive.rb +20 -0
  161. data/lib/openhab/yard/tags/group_directive.rb +24 -0
  162. data/lib/openhab/yard/tags/library.rb +3 -0
  163. data/lib/openhab/yard.rb +32 -0
  164. metadata +504 -0
@@ -0,0 +1,348 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenHAB
6
+ # rubocop:disable Layout/LineLength
7
+
8
+ #
9
+ # Provides access to the OpenHAB logging facilities using Ruby logging methods
10
+ #
11
+ # Logging is available everywhere through the {#logger} object.
12
+ #
13
+ # The logging prefix is `org.openhab.automation.jrubyscripting`.
14
+ # Logging within file-based rules will have the name of the file appended to
15
+ # the logger name. Logging inside of a rule will have the id of the rule
16
+ # appended to the logger name. Any classes will have the full class anem
17
+ # appended to the logger name.
18
+ #
19
+ # @example The following entries are in a file named 'log_test.rb'
20
+ # logger.trace('Test logging at trace') # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.log_test] - Test logging at trace
21
+ # logger.debug('Test logging at debug') # 2020-12-03 18:05:32.020 [DEBUG] [org.openhab.automation.jrubyscripting.log_test] - Test logging at debug
22
+ # logger.warn('Test logging at warn') # 2020-12-03 18:05:41.817 [WARN ] [org.openhab.automation.jrubyscripting.log_test] - Test logging at warn
23
+ # logger.info('Test logging at info') # 2020-12-03 18:05:41.817 [INFO ] [org.openhab.automation.jrubyscripting.log_test] - Test logging at info
24
+ # logger.error('Test logging at error') # 2020-12-03 18:06:02.021 [ERROR] [org.openhab.automation.jrubyscripting.log_test] - Test logging at error
25
+ #
26
+ # @example The following entries are in a file named 'log_test.rb'
27
+ # rule 'foo' do
28
+ # run { logger.trace('Test logging at trace') } # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.foo] - Test logging at trace
29
+ # on_start
30
+ # end
31
+ #
32
+ #
33
+ # @example A log entry from inside a class
34
+ # class MyClass
35
+ # def initialize
36
+ # logger.trace("hi!") # 2020-12-03 18:05:20.903 [TRACE] [org.openhab.automation.jrubyscripting.MyClass] - hi!
37
+ # end
38
+ # end
39
+ #
40
+ module Log
41
+ # rubocop:enable Layout/LineLength
42
+
43
+ # @!visibility private
44
+ def self.included(base)
45
+ return if base.singleton_class?
46
+
47
+ base.singleton_class.include(self)
48
+ end
49
+
50
+ protected
51
+
52
+ #
53
+ # Retrieve the {Logger} for this class.
54
+ #
55
+ # @return [Logger]
56
+ #
57
+ def logger
58
+ # no caching on `main`
59
+ if (instance_of?(Object) && !singleton_methods.empty?) ||
60
+ # also pretend loggers in example groups are in the top-level
61
+ (defined?(::RSpec::Core::ExampleGroup) && is_a?(Module) && self < ::RSpec::Core::ExampleGroup)
62
+ return Log.logger(:main)
63
+ end
64
+ return @logger ||= Log.logger(self) if equal?(self.class) || is_a?(Module)
65
+
66
+ self.class.logger
67
+ end
68
+
69
+ @loggers = {}
70
+ class << self
71
+ #
72
+ # Retrieve a {Logger} for a particular object.
73
+ #
74
+ # @param [Module,String] object Object the logger is for, or explicit name of the logger.
75
+ # @return [Logger]
76
+ #
77
+ def logger(object)
78
+ case object
79
+ when Module
80
+ name = Logger::PREFIX
81
+ klass = java_klass(object)
82
+ name += ".#{klass.name.gsub("::", ".")}" if klass.name
83
+ when String
84
+ name = object
85
+ when :main
86
+ name = "#{Logger::PREFIX}.#{rules_file.tr_s(":", "_")
87
+ .gsub(/[^A-Za-z0-9_.-]/, "")}"
88
+ return @loggers[name] ||= BiLogger.new(Logger.new(name))
89
+ end
90
+
91
+ @loggers[name] ||= Logger.new(name)
92
+ end
93
+
94
+ private
95
+
96
+ # Get the appropriate java class for the supplied klass if the supplied
97
+ # class is a java class
98
+ # @param [Class] klass to inspect
99
+ # @return Class or Java class of supplied class
100
+ def java_klass(klass)
101
+ if klass.respond_to?(:java_class) &&
102
+ klass.java_class &&
103
+ !klass.java_class.name.start_with?("org.jruby.Ruby") &&
104
+ !klass.java_class.name.start_with?("org.jruby.gen")
105
+ klass = klass.java_class
106
+ end
107
+ klass
108
+ end
109
+
110
+ #
111
+ # Figure out the log prefix
112
+ #
113
+ # @return [String] Prefix for log messages
114
+ #
115
+ def rules_file
116
+ caller_locations(3, 2).map(&:path)
117
+ .grep_v(%r{lib/openhab/log\.rb})
118
+ .first
119
+ .then { |caller| File.basename(caller, ".*") if caller }
120
+ end
121
+ end
122
+ end
123
+
124
+ #
125
+ # Ruby Logger that forwards messages at appropriate levels to OpenHAB Logger
126
+ #
127
+ class Logger
128
+ # The base prefix for all loggers from this gem.
129
+ PREFIX = "org.openhab.automation.jrubyscripting"
130
+
131
+ # @return [Array<symbol>] Supported logging levels
132
+ LEVELS = %i[trace debug warn info error].freeze
133
+
134
+ #
135
+ # Regex for matching internal calls in a stack trace
136
+ #
137
+ INTERNAL_CALL_REGEX = %r{(openhab-jrubyscripting-.*/lib)|org[./]jruby}.freeze
138
+ private_constant :INTERNAL_CALL_REGEX
139
+
140
+ #
141
+ # Regex for matching internal calls in a java stack trace
142
+ #
143
+ EXCLUDED_JAVA_PACKAGES = /jdk\.internal\.reflect|java\.lang\.reflect|org\.openhab|java\.lang\.Thread\.run/.freeze
144
+ private_constant :EXCLUDED_JAVA_PACKAGES
145
+
146
+ #
147
+ # Regex for matching internal calls in a java stack trace
148
+ #
149
+ JAVA_INTERNAL_CALL_REGEX = Regexp.union(INTERNAL_CALL_REGEX, EXCLUDED_JAVA_PACKAGES).freeze
150
+ private_constant :JAVA_INTERNAL_CALL_REGEX
151
+
152
+ class << self
153
+ # The root logger (all of OpenHAB)
154
+ # @return [Logger]
155
+ def root
156
+ Log.logger(org.slf4j.Logger::ROOT_LOGGER_NAME)
157
+ end
158
+
159
+ # The root logger for this gem
160
+ # @return [Logger]
161
+ def gem_root
162
+ Log.logger(PREFIX)
163
+ end
164
+
165
+ # The events logger (events.log)
166
+ # @return [Logger]
167
+ def events
168
+ Log.logger("openhab.event")
169
+ end
170
+
171
+ # @!visibility private
172
+ def log_service
173
+ @log_service = OSGi.service("org.apache.karaf.log.core.LogService")
174
+ end
175
+
176
+ private
177
+
178
+ # @!macro def_level_method
179
+ # @!method $1(msg = nil)
180
+ #
181
+ # Log a message at $1 level.
182
+ #
183
+ # @param msg [Object, nil] The log message
184
+ # @yield
185
+ # Pass a block to delay generating the log message until it's
186
+ # confirmed that logging is enabled at $1 level.
187
+ # @yieldreturn [Object, nil] The log message
188
+ # @return [void]
189
+ #
190
+ # @example
191
+ # logger.$1 do
192
+ # total = Item1.state + Item2.state
193
+ # average = total / 2
194
+ # "Total: #{total}, Average: #{average}"
195
+ # end
196
+ #
197
+ def def_level_method(level)
198
+ define_method(level) do |msg = nil, &block|
199
+ log(severity: level, msg: msg, &block)
200
+ end
201
+ end
202
+
203
+ # @!macro def_level_predicate
204
+ # @!method $1?
205
+ #
206
+ # If the logger is enabled at $1 level.
207
+ #
208
+ # @return [true,false]
209
+ #
210
+ def def_level_predicate(level)
211
+ define_method("#{level}?") { @slf4j_logger.send("is_#{level}_enabled") }
212
+ end
213
+ end
214
+
215
+ # @!visibility private
216
+ #
217
+ # Create a new logger
218
+ #
219
+ # @param [String] name of the logger
220
+ #
221
+ def initialize(name)
222
+ @slf4j_logger = org.slf4j.LoggerFactory.getLogger(name)
223
+ end
224
+
225
+ # The logger name
226
+ # @return [String]
227
+ def name
228
+ @slf4j_logger.name
229
+ end
230
+
231
+ # @return [String]
232
+ def inspect
233
+ "#<OpenHAB::Logger #{name}>"
234
+ end
235
+ alias_method :to_s, :inspect
236
+
237
+ # @!attribute [rw] level
238
+ # @return [:error,:warn,:info,:debug,:trace] The current log level
239
+ def level
240
+ Logger.log_service.get_level(name)[name]&.downcase&.to_sym
241
+ end
242
+
243
+ def level=(level)
244
+ Logger.log_service.set_level(name, level.to_s)
245
+ end
246
+
247
+ def_level_method(:error)
248
+ def_level_predicate(:error)
249
+ def_level_method(:warn)
250
+ def_level_predicate(:warn)
251
+ def_level_method(:info)
252
+ def_level_predicate(:info)
253
+ def_level_method(:debug)
254
+ def_level_predicate(:debug)
255
+ def_level_method(:trace)
256
+ def_level_predicate(:trace)
257
+
258
+ #
259
+ # Print error and stack trace without calls to internal classes
260
+ #
261
+ # @param [Exception] exception A rescued error
262
+ # @return [void]
263
+ #
264
+ def log_exception(exception)
265
+ exception = clean_backtrace(exception)
266
+ error do
267
+ "#{exception.message} (#{exception.class})\n#{name}#{exception.backtrace&.join("\n")}"
268
+ end
269
+ end
270
+
271
+ private
272
+
273
+ #
274
+ # Cleans the backtrace of an error to remove internal calls. If logging is set
275
+ # to debug or lower, the full backtrace is kept
276
+ #
277
+ # @param [Exception] error An exception to be cleaned
278
+ #
279
+ # @return [Exception] the exception, potentially with a cleaned backtrace.
280
+ #
281
+ def clean_backtrace(error)
282
+ return error if debug?
283
+
284
+ if error.respond_to? :backtrace_locations
285
+ backtrace = error.backtrace_locations.map(&:to_s).grep_v(INTERNAL_CALL_REGEX)
286
+ error.set_backtrace(backtrace)
287
+ elsif error.respond_to? :stack_trace
288
+ backtrace = error.stack_trace.reject { |line| JAVA_INTERNAL_CALL_REGEX.match? line.to_s }
289
+ error.set_stack_trace(backtrace)
290
+ end
291
+ error
292
+ end
293
+
294
+ #
295
+ # Log a message to the OpenHAB Logger
296
+ #
297
+ # @param [Symbol] severity Severity to log message at
298
+ # @param [Object] msg to log, if no msg supplied and a block is provided,
299
+ # the msg is taken from the result of the block
300
+ #
301
+ def log(severity:, msg: nil)
302
+ raise ArgumentError, "Unknown Severity #{severity}" unless LEVELS.include? severity
303
+
304
+ # Dynamically check enablement of underlying logger
305
+ return unless send("#{severity}?")
306
+
307
+ # Process block if no message provided
308
+ msg = yield if msg.nil? && block_given?
309
+
310
+ @slf4j_logger.send(severity, msg.to_s)
311
+ end
312
+ end
313
+
314
+ module Log
315
+ # Logger that changes its backing logger depending on thread context
316
+ class BiLogger < Logger
317
+ @rule_loggers = {}
318
+ class << self
319
+ # class shared cache of loggers-per-rule
320
+ attr_reader :rule_loggers
321
+ end
322
+
323
+ def initialize(file_logger) # rubocop:disable Lint/MissingSuper
324
+ @file_logger = file_logger
325
+ end
326
+
327
+ # The current logger - the file logger if rule_uid is nil,
328
+ # otherwise a logger specific to the rule.
329
+ def current_logger
330
+ return @file_logger unless (rule_uid = Thread.current[:openhab_rule_uid])
331
+
332
+ rule_type = Thread.current[:openhab_rule_type]
333
+ full_id = "#{rule_type}:#{rule_uid}"
334
+
335
+ self.class.rule_loggers[full_id] ||= Logger.new("#{Logger::PREFIX}.#{rule_type}.#{rule_uid.tr_s(":", "_")
336
+ .gsub(/[^A-Za-z0-9_.-]/, "")}")
337
+ end
338
+
339
+ extend Forwardable
340
+ def_delegators :current_logger, *(Logger.public_instance_methods.select do |m|
341
+ Logger.instance_method(m).owner == Logger
342
+ end - BasicObject.public_instance_methods)
343
+ end
344
+ private_constant :BiLogger
345
+ end
346
+
347
+ Object.include(Log)
348
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ #
5
+ # OSGi services interface
6
+ #
7
+ module OSGi
8
+ class << self
9
+ #
10
+ # @param name [String] The service name
11
+ # @param filter [String] Filter for service names. See https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/Filter.html
12
+ #
13
+ # @return [Object]
14
+ #
15
+ def service(name, filter: nil)
16
+ services(name, filter: filter).first
17
+ end
18
+
19
+ #
20
+ # @param name [String] The service name
21
+ # @param filter [String] Filter for service names. See https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/Filter.html
22
+ #
23
+ # @return [Array<Object>] An array of services
24
+ #
25
+ def services(name, filter: nil)
26
+ (bundle_context.get_service_references(name, filter) || []).map do |reference|
27
+ logger.trace "OSGi service found for '#{name}' using OSGi Service Reference #{reference}"
28
+ bundle_context.get_service(reference)
29
+ end
30
+ end
31
+
32
+ #
33
+ # Register a new service instance with OSGi
34
+ #
35
+ # @param [Object] instance The service instance
36
+ # @param [Module] interfaces The interfaces to register this service for.
37
+ # If not provided, it will default to all Java interfaces the instance
38
+ # implements.
39
+ # @param [Hash] properties The service registration properties.
40
+ # @return [org.osgi.framework.ServiceRegistration]
41
+ #
42
+ def register_service(instance, *interfaces, **properties)
43
+ if interfaces.empty?
44
+ interfaces = instance.class.ancestors.select { |k| k.respond_to?(:java_class) && k.java_class&.interface? }
45
+ end
46
+
47
+ bundle = org.osgi.framework.FrameworkUtil.get_bundle(interfaces.first)
48
+ bundle.bundle_context.register_service(
49
+ interfaces.map(&:java_class).map(&:name).to_java(java.lang.String),
50
+ instance,
51
+ java.util.Hashtable.new(properties)
52
+ )
53
+ end
54
+
55
+ private
56
+
57
+ # @!attribute [r] bundle_context
58
+ # @return [org.osgi.framework.BundleContext] OSGi bundle context
59
+ def bundle_context
60
+ @bundle_context ||= bundle.bundle_context
61
+ end
62
+
63
+ # @!attribute [r] bundle
64
+ # @return [org.osgi.framework.Bundle] The OSGi Bundle for ScriptExtension Class
65
+ def bundle
66
+ @bundle ||= org.osgi.framework.FrameworkUtil.getBundle($scriptExtension.class)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module RSpec
5
+ #
6
+ # Contains configuration for how the OpenHAB instance should be set
7
+ # up for the testing environment.
8
+ #
9
+ module Configuration
10
+ class << self
11
+ #
12
+ # Copy binding configuration from the root OpenHAB instance.
13
+ #
14
+ # Default `true`.
15
+ # @return [true, false]
16
+ #
17
+ attr_accessor :include_bindings
18
+
19
+ #
20
+ # Copy the JSONDB (managed thing and item configuration) from the root
21
+ # OpenHAB instance.
22
+ #
23
+ # Default `true`.
24
+ #
25
+ # @return [true, false]
26
+ #
27
+ attr_accessor :include_jsondb
28
+
29
+ #
30
+ # Use a private (empty) confdir (scripts, rules, items, and things
31
+ # files), instead of sharing with the root OpenHAB instance.
32
+ #
33
+ # Default `false`.
34
+ #
35
+ # @return [true, false]
36
+ #
37
+ attr_accessor :private_confdir
38
+
39
+ #
40
+ # Use the root OpenHAB instance directly, rather than creating a
41
+ # private (but linked) instance.
42
+ #
43
+ # Default `false`.
44
+ #
45
+ # @return [true, false]
46
+ #
47
+ attr_accessor :use_root_instance
48
+ end
49
+
50
+ self.include_bindings = true
51
+ self.include_jsondb = true
52
+ self.private_confdir = false
53
+ self.use_root_instance = false
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module RSpec
5
+ # ::RSpec::ExampleGroup extensions
6
+ module ExampleGroup
7
+ # Extensions for ::RSpec::ExampleGroup's singleton class.
8
+ module ClassMethods
9
+ # @!attribute [w] mock_timers
10
+ #
11
+ # Set if timers should be mocked for this example group.
12
+ #
13
+ # @param value [true, false, nil]
14
+ # @return [true, false, nil]
15
+ #
16
+ # @example
17
+ # describe "my_rule" do
18
+ # self.mock_timers = false
19
+ #
20
+ # it "runs a timer" do
21
+ # expect(self.class.mock_timers?).to be false
22
+ # end
23
+ # end
24
+ #
25
+ def mock_timers=(value)
26
+ @mock_timers = value
27
+ end
28
+
29
+ #
30
+ # If timers are mocked for this example group
31
+ #
32
+ # It will search through parent groups until it finds one where it's
33
+ # explicitly defined, or defaults to `true` if none are.
34
+ #
35
+ # @return [true, false]
36
+ #
37
+ def mock_timers?
38
+ return @mock_timers if instance_variable_defined?(:@mock_timers) && !@mock_timers.nil?
39
+ return superclass.mock_timers? if superclass.is_a?(ClassMethods)
40
+
41
+ true
42
+ end
43
+
44
+ # @!attribute [w] consistent_proxies
45
+ #
46
+ # Set if Items and Thing proxies should return consistent objects.
47
+ #
48
+ # @param value [true, false, nil]
49
+ # @return [true, false, nil]
50
+ #
51
+ # @example
52
+ # describe "my_rule" do
53
+ # self.consistent_proxies = false
54
+ #
55
+ # it "does something" do
56
+ # expect(self.class.consistent_proxies?).to be false
57
+ # end
58
+ # end
59
+ #
60
+ # @see #consistent_proxies?
61
+ #
62
+ def consistent_proxies=(value)
63
+ @consistent_proxies = value
64
+ end
65
+
66
+ #
67
+ # If Item and Thing proxies will consistently return the same object.
68
+ #
69
+ # Useful for mocking and using the `be` matcher.
70
+ #
71
+ # It will search through parent groups until it finds one where it's
72
+ # explicitly defined, or defaults to `true` if none are.
73
+ #
74
+ # @return [true, false]
75
+ #
76
+ def consistent_proxies?
77
+ return @consistent_proxies if instance_variable_defined?(:@consistent_proxies) && !@consistent_proxies.nil?
78
+ return superclass.consistent_proxies? if superclass.is_a?(ClassMethods)
79
+
80
+ true
81
+ end
82
+ end
83
+
84
+ # @!visibility private
85
+ def self.included(klass)
86
+ klass.singleton_class.include(ClassMethods)
87
+ end
88
+ end
89
+ end
90
+ end