openhab-jrubyscripting 5.0.0.rc2 → 5.0.0.rc3

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/items/generic_item.rb +13 -5
  3. data/lib/openhab/core/items/metadata/hash.rb +17 -34
  4. data/lib/openhab/core/items/persistence.rb +2 -0
  5. data/lib/openhab/core/items/semantics/enumerable.rb +6 -4
  6. data/lib/openhab/core/profile_factory.rb +2 -0
  7. data/lib/openhab/core/provider.rb +8 -1
  8. data/lib/openhab/core/rules/provider.rb +25 -0
  9. data/lib/openhab/core/rules/registry.rb +76 -0
  10. data/lib/openhab/core/rules/rule.rb +150 -0
  11. data/lib/openhab/core/rules.rb +25 -0
  12. data/lib/openhab/core/timer.rb +5 -7
  13. data/lib/openhab/core/types.rb +1 -1
  14. data/lib/openhab/core.rb +0 -16
  15. data/lib/openhab/core_ext/java/list.rb +436 -0
  16. data/lib/openhab/core_ext/java/map.rb +66 -0
  17. data/lib/openhab/core_ext/java/zoned_date_time.rb +1 -2
  18. data/lib/openhab/core_ext/ruby/date.rb +2 -0
  19. data/lib/openhab/core_ext/ruby/date_time.rb +53 -0
  20. data/lib/openhab/core_ext/ruby/time.rb +88 -86
  21. data/lib/openhab/dsl/events/watch_event.rb +1 -1
  22. data/lib/openhab/dsl/items/builder.rb +8 -3
  23. data/lib/openhab/dsl/items/ensure.rb +6 -2
  24. data/lib/openhab/dsl/items/timed_command.rb +10 -11
  25. data/lib/openhab/dsl/rules/automation_rule.rb +36 -13
  26. data/lib/openhab/dsl/rules/builder.rb +99 -8
  27. data/lib/openhab/dsl/rules/name_inference.rb +0 -5
  28. data/lib/openhab/dsl/rules/terse.rb +1 -2
  29. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +17 -53
  30. data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +0 -3
  31. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +1 -1
  32. data/lib/openhab/dsl/rules.rb +0 -21
  33. data/lib/openhab/dsl/thread_local.rb +2 -2
  34. data/lib/openhab/dsl/timer_manager.rb +3 -1
  35. data/lib/openhab/dsl/version.rb +1 -1
  36. data/lib/openhab/dsl.rb +12 -105
  37. data/lib/openhab/log.rb +2 -2
  38. data/lib/openhab/rspec/example_group.rb +42 -0
  39. data/lib/openhab/rspec/helpers.rb +31 -8
  40. data/lib/openhab/rspec/hooks.rb +3 -6
  41. data/lib/openhab/rspec/karaf.rb +45 -27
  42. data/lib/openhab/rspec/mocks/synchronous_executor.rb +11 -4
  43. data/lib/openhab/rspec/mocks/timer.rb +2 -1
  44. data/lib/openhab/rspec/suspend_rules.rb +4 -2
  45. metadata +23 -2
@@ -0,0 +1,436 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @!visibility private
4
+ module Java::JavaUtil::List # rubocop:disable Style/ClassAndModuleChildren
5
+ extend Forwardable
6
+
7
+ def_delegators :to_a,
8
+ :&,
9
+ :*,
10
+ :|,
11
+ :bsearch_index,
12
+ :difference,
13
+ :flatten,
14
+ :intersection,
15
+ :pack,
16
+ :product,
17
+ :repeated_combination,
18
+ :repeated_permutation,
19
+ :reverse,
20
+ :rotate,
21
+ :sample,
22
+ :shelljoin,
23
+ :shuffle,
24
+ :transpose,
25
+ :union
26
+
27
+ def assoc(obj)
28
+ find { |v| (v.is_a?(Array) || v.is_a?(self.class)) && v[0] == obj }
29
+ end
30
+
31
+ def at(index)
32
+ self[index]
33
+ end
34
+
35
+ def bsearch(&block)
36
+ raise NotImplementedError unless block
37
+
38
+ r = bsearch_index(&block)
39
+ self[r] if r
40
+ end
41
+
42
+ def combination(n, &block) # rubocop:disable Naming/MethodParameterName
43
+ r = to_a.combination(n, &block)
44
+ block ? self : r
45
+ end
46
+
47
+ def compact
48
+ reject(&:nil?)
49
+ end
50
+
51
+ def compact!
52
+ reject!(&:nil?)
53
+ end
54
+
55
+ def concat(*other_arrays)
56
+ other_arrays.each { |array| add_all(array) }
57
+ self
58
+ end
59
+
60
+ def deconstruct
61
+ self
62
+ end
63
+
64
+ def delete(obj)
65
+ last = nil
66
+ found = false
67
+ loop do
68
+ i = index(obj)
69
+ break if i.nil?
70
+
71
+ found = true
72
+ last = remove(i)
73
+ end
74
+
75
+ return yield(obj) if !found && block_given?
76
+
77
+ last
78
+ end
79
+
80
+ def delete_at(index)
81
+ index = length + index if index.negative?
82
+ return if index.negative? || index >= length
83
+
84
+ remove(index)
85
+ end
86
+
87
+ def delete_if
88
+ raise NotImplementedError unless block_given?
89
+
90
+ it = list_iterator
91
+ while it.has_next? # rubocop:disable Style/WhileUntilModifier
92
+ it.remove if yield(it.next)
93
+ end
94
+ self
95
+ end
96
+
97
+ def dig(index, *identifiers)
98
+ return self[index] if identifiers.empty?
99
+
100
+ self[index]&.dig(*identifiers)
101
+ end
102
+
103
+ def each_index(&block)
104
+ r = (0...length)
105
+ return r.each unless block
106
+
107
+ r.each(&block)
108
+ self
109
+ end
110
+
111
+ def fetch(index, *default_value)
112
+ if default_value.length > 1
113
+ raise ArgumentError,
114
+ "wrong number of arguments calling `fetch` (given #{default_value.length - 1}, expected 1..2)"
115
+ end
116
+
117
+ original_index = index
118
+ index = length + index if index.negative?
119
+ return self[index] if index >= 0 && index < length
120
+
121
+ return default_value.first unless default_value.empty?
122
+ return yield(original_index) if block_given?
123
+
124
+ raise IndexError, "index #{index} out of list"
125
+ end
126
+
127
+ def fill(*args)
128
+ if block_given?
129
+ unless (0..2).cover?(args.length)
130
+ raise ArgumentError,
131
+ "wrong number of arguments calling `fill` (given #{args.length}, expected 1..3)"
132
+ end
133
+ else
134
+ unless (1..3).cover?(args.length)
135
+ raise ArgumentError,
136
+ "wrong number of arguments calling `fill` (given #{args.length}, expected 1..2)"
137
+ end
138
+ end
139
+
140
+ obj = args.shift unless block_given?
141
+
142
+ if args.length == 1 && args.first.is_a?(Range)
143
+ range = args.first
144
+
145
+ range = Range.new(length + range.begin, range.end, range.exclude_end?) if range.begin.negative?
146
+ range = Range.new(range.begin, length + range.end, range.exclude_end?) if range.end&.negative?
147
+ return self if range.begin.negative? || (range.end && range.end < range.begin)
148
+ else
149
+ first, count = *args
150
+ return self if count&.negative?
151
+
152
+ first ||= 0
153
+
154
+ first = length + first if first.negative?
155
+ range = count ? first...(first + count) : first..
156
+ end
157
+
158
+ add(nil) while length < range.begin && count
159
+
160
+ start = range.begin
161
+ start = 0 if start.negative?
162
+ start = length if start > length
163
+ it = list_iterator(start)
164
+
165
+ while range.cover?(it.next_index)
166
+ break if range.end.nil? && !it.has_next?
167
+
168
+ obj = yield(it.next_index) if block_given?
169
+ if it.has_next?
170
+ it.next
171
+ it.set(obj)
172
+ else
173
+ it.add(obj)
174
+ end
175
+ end
176
+
177
+ self
178
+ end
179
+
180
+ def flatten!(*args)
181
+ if args.length > 1
182
+ raise ArgumentError,
183
+ "wrong number of arguments calling `flatten` (given #{args.length}, expect 0..1)"
184
+ end
185
+
186
+ it = list_iterator
187
+
188
+ args = [args.first - 1] unless args.empty?
189
+ done = args.first == 0 # rubocop:disable Style/NumericPredicate
190
+
191
+ changed = false
192
+ while it.has_next?
193
+ element = it.next
194
+ next unless element.respond_to?(:to_ary)
195
+
196
+ changed = true
197
+ it.remove
198
+ arr = element.to_ary
199
+ arr = arr.flatten(*args) unless done
200
+ arr.each do |e|
201
+ it.add(e)
202
+ end
203
+ end
204
+ changed ? self : nil
205
+ end
206
+
207
+ def insert(index, *objects)
208
+ return self if objects.empty?
209
+
210
+ raise IndexError, "index #{index} too small for list, minimum: #{-length}" if index < -length
211
+
212
+ index = length + index + 1 if index.negative?
213
+
214
+ add(nil) while length < index
215
+ add_all(index, objects)
216
+ self
217
+ end
218
+
219
+ def intersect?(other_ary)
220
+ !(self & other_ary).empty?
221
+ end
222
+
223
+ def keep_if?
224
+ raise NotImplementedError unless block_given?
225
+
226
+ it = list_iterator
227
+ while it.has_next? # rubocop:disable Style/WhileUntilModifier
228
+ it.remove unless yield(it.next)
229
+ end
230
+ self
231
+ end
232
+
233
+ def map!(&block)
234
+ raise NotImplementedError unless block
235
+
236
+ replace_all(&block)
237
+ self
238
+ end
239
+
240
+ def permutation(n, &block) # rubocop:disable Naming/MethodParameterName
241
+ r = to_a.permutation(n, &block)
242
+ block ? self : r
243
+ end
244
+
245
+ def pop(*args)
246
+ if args.length > 1
247
+ raise ArgumentError,
248
+ "wrong number of arguments calling `pop` (given #{args.length}, expected 0..1)"
249
+ end
250
+
251
+ if args.empty?
252
+ return if empty?
253
+
254
+ return remove(length - 1)
255
+ end
256
+
257
+ count = args.first
258
+ start = [length - count, 0].max
259
+ result = self[start..-1].to_a # rubocop:disable Style/SlicingWithRange
260
+ it = list_iterator(start)
261
+ while it.has_next?
262
+ it.next
263
+ it.remove
264
+ end
265
+ result
266
+ end
267
+
268
+ def push(*objects)
269
+ add_all(objects)
270
+ self
271
+ end
272
+ alias_method :append, :push
273
+
274
+ def rassoc(obj)
275
+ find { |v| (v.is_a?(Array) || v.is_a?(self.class)) && v[1] == obj }
276
+ end
277
+
278
+ def reject!
279
+ raise NotImplementedError unless block_given?
280
+
281
+ it = list_iterator
282
+ changed = false
283
+ while it.has_next
284
+ if yield(it.next)
285
+ changed = true
286
+ it.remove
287
+ end
288
+ end
289
+ self if changed
290
+ end
291
+
292
+ def repeated_combination(n, &block) # rubocop:disable Naming/MethodParameterName
293
+ r = to_a.repeated_combination(n, &block)
294
+ block ? self : r
295
+ end
296
+
297
+ def repeated_permutation(n, &block) # rubocop:disable Naming/MethodParameterName
298
+ r = to_a.repeated_permutation(n, &block)
299
+ block ? self : r
300
+ end
301
+
302
+ def replace(other_array)
303
+ clear
304
+ add_all(other_array)
305
+ self
306
+ end
307
+
308
+ def reverse!
309
+ replace(reverse)
310
+ self
311
+ end
312
+
313
+ def rotate!(count = 1)
314
+ count = count % length
315
+ push(*shift(count))
316
+ self
317
+ end
318
+
319
+ def select!
320
+ raise NotImplementedError unless block_given?
321
+
322
+ it = list_iterator
323
+ changed = false
324
+ while it.has_next?
325
+ unless yield(it.next)
326
+ changed = true
327
+ it.remove
328
+ end
329
+ end
330
+ self if changed
331
+ end
332
+
333
+ def shift(*args)
334
+ if args.length > 1
335
+ raise ArgumentError,
336
+ "wrong number of arguments calling `shift` (given #{args.length}, expected 0..1)"
337
+ end
338
+
339
+ if args.empty?
340
+ return if empty?
341
+
342
+ return remove(0)
343
+ end
344
+
345
+ count = args.first
346
+ result = self[0...count].to_a
347
+ it = list_iterator
348
+ count.times do
349
+ break unless it.has_next?
350
+
351
+ it.next
352
+ it.remove
353
+ end
354
+ result
355
+ end
356
+
357
+ def shuffle!(*args)
358
+ replace(shuffle(*args))
359
+ end
360
+
361
+ def slice(*args)
362
+ self[*args]
363
+ end
364
+
365
+ def slice!(*args)
366
+ unless (1..2).cover?(args.length)
367
+ raise ArgumentError,
368
+ "wrong number of arguments calling `slice!` (given #{args.length}, expected 1..2)"
369
+ end
370
+
371
+ return delete_at(args.first) if args.length == 1 && !args.first.is_a?(Range)
372
+
373
+ start = args.first
374
+ start = start.begin if start.is_a?(Range)
375
+ start = length + start if start.negative?
376
+ return nil if start.negative? || start >= length
377
+
378
+ result = slice(*args).to_a
379
+
380
+ it = list_iterator(start)
381
+ result.length.times do
382
+ it.next
383
+ it.remove
384
+ end
385
+ result
386
+ end
387
+
388
+ def sort_by!
389
+ raise NotImplementedError unless block_given?
390
+
391
+ sort { |a, b| (yield a) <=> (yield b) }
392
+ self
393
+ end
394
+
395
+ def uniq!
396
+ seen = Set.new
397
+
398
+ it = list_iterator
399
+ changed = false
400
+ while it.has_next?
401
+ n = it.next
402
+ n = yield(n) if block_given?
403
+ if seen.include?(n)
404
+ changed = true
405
+ it.remove
406
+ end
407
+ seen << n
408
+ end
409
+ self if changed
410
+ end
411
+
412
+ def unshift(*objects)
413
+ add_all(0, objects)
414
+ self
415
+ end
416
+ alias_method :prepend, :unshift
417
+
418
+ def values_at(*indexes)
419
+ result = []
420
+ indexes.each do |index|
421
+ if index.is_a?(Range)
422
+ partial_result = self[index]
423
+ result.concat(partial_result)
424
+ result.fill(nil, result.length, index.count - partial_result.length)
425
+ else
426
+ index = length + index if index.negative?
427
+ result << if index.negative? || index >= length
428
+ nil
429
+ else
430
+ self[index]
431
+ end
432
+ end
433
+ end
434
+ result
435
+ end
436
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @!visibility private
4
+ module Java::JavaUtil::Map # rubocop:disable Style/ClassAndModuleChildren
5
+ def compact
6
+ reject { |_k, v| v.nil? }
7
+ end
8
+
9
+ def compact!
10
+ reject! { |_k, v| v.nil? }
11
+ self
12
+ end
13
+
14
+ def deconstruct_keys
15
+ self
16
+ end
17
+
18
+ def except(*keys)
19
+ reject { |k, _v| keys.include?(k) }
20
+ end
21
+
22
+ def slice(*keys)
23
+ select { |k, _v| keys.include?(k) }
24
+ end
25
+
26
+ def transform_keys(hash2 = nil)
27
+ raise NotImplementedError unless hash2 || block_given?
28
+
29
+ map do |k, v| # rubocop:disable Style/MapToHash
30
+ if hash2&.key?(k)
31
+ [hash2[k], v]
32
+ elsif block_given?
33
+ [(yield k), v]
34
+ else
35
+ [k, v]
36
+ end
37
+ end.to_h
38
+ end
39
+
40
+ def transform_keys!(hash2 = nil)
41
+ raise NotImplementedError unless hash2 || block_given?
42
+
43
+ keys.each do |k|
44
+ if hash2&.key?(k)
45
+ self[hash2[k]] = delete(k)
46
+ elsif block_given?
47
+ new_k = yield k
48
+ self[new_k] = delete(k) unless new_k == k
49
+ end
50
+ end
51
+ self
52
+ end
53
+
54
+ def transform_values
55
+ map do |k, v| # rubocop:disable Style/MapToHash, Style/HashTransformValues
56
+ [k, (yield v)]
57
+ end.to_h
58
+ end
59
+
60
+ def transform_values!
61
+ replace_all do |_k, v|
62
+ yield v
63
+ end
64
+ self
65
+ end
66
+ end
@@ -25,8 +25,7 @@ module OpenHAB
25
25
  # @return [ZonedDateTime] If other is a TemporalAmount
26
26
  def -(other)
27
27
  if other.respond_to?(:to_zoned_date_time)
28
- nanos = other.to_zoned_date_time.until(self, java.time.temporal.ChronoUnit::NANOS)
29
- (nanos.to_f / 1_000_000_000).seconds
28
+ java.time.Duration.between(other.to_zoned_date_time, self)
30
29
  elsif other.is_a?(Numeric)
31
30
  minus(other.seconds)
32
31
  else
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "date"
4
+
3
5
  # Extensions to Date
4
6
  class Date
5
7
  #
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "forwardable"
5
+
6
+ # DateTime inherits from Date, but is more similar to Time semantically.
7
+ # So it avoid alias_method chain bombs, and to ensure the correct end methods
8
+ # exist here, we define the important methods from Time here as well.
9
+
10
+ # Extensions to DateTime
11
+ class DateTime < Date
12
+ extend Forwardable
13
+
14
+ # (see Time#plus_with_temporal)
15
+ def plus_with_temporal(other)
16
+ return to_zoned_date_time + other if other.is_a?(java.time.temporal.TemporalAmount)
17
+
18
+ plus_without_temporal(other)
19
+ end
20
+ # alias_method :plus_without_temporal, :+ # already done by Date
21
+ alias_method :+, :plus_with_temporal
22
+
23
+ # (see Time#minus_with_temporal)
24
+ def minus_with_temporal(other)
25
+ return to_zoned_date_time - other if other.is_a?(java.time.temporal.TemporalAmount)
26
+
27
+ # Exclude subtracting against the same class
28
+ if other.respond_to?(:to_zoned_date_time) && !other.is_a?(self.class)
29
+ return to_zoned_date_time - other.to_zoned_date_time
30
+ end
31
+
32
+ minus_without_temporal(other)
33
+ end
34
+ # alias_method :minus_without_temporal, :- # already done by Date
35
+ alias_method :-, :minus_with_temporal
36
+
37
+ # @!method to_local_time
38
+ # @return [LocalTime]
39
+ def_delegator :to_zoned_date_time, :to_local_time
40
+
41
+ # (see Time#to_zoned_date_time)
42
+ def to_zoned_date_time(context = nil) # rubocop:disable Lint/UnusedMethodArgument
43
+ to_java(ZonedDateTime)
44
+ end
45
+
46
+ # (see Time#coerce)
47
+ def coerce(other)
48
+ return unless other.respond_to?(:to_zoned_date_time)
49
+
50
+ zdt = to_zoned_date_time
51
+ [other.to_zoned_date_time(zdt), zdt]
52
+ end
53
+ end