openhab-jrubyscripting 5.0.0.rc11 → 5.0.0.rc.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/exec.rb +41 -41
  3. data/lib/openhab/core/actions/transformation.rb +3 -3
  4. data/lib/openhab/core/actions.rb +1 -1
  5. data/lib/openhab/core/events/item_command_event.rb +31 -31
  6. data/lib/openhab/core/events/item_state_changed_event.rb +41 -18
  7. data/lib/openhab/core/events/item_state_event.rb +46 -18
  8. data/lib/openhab/core/items/date_time_item.rb +3 -2
  9. data/lib/openhab/core/items/generic_item.rb +119 -1
  10. data/lib/openhab/core/items/item.rb +63 -9
  11. data/lib/openhab/core/items/metadata/hash.rb +1 -1
  12. data/lib/openhab/core/items/metadata/namespace_hash.rb +10 -2
  13. data/lib/openhab/core/items/metadata/provider.rb +2 -2
  14. data/lib/openhab/core/items/persistence.rb +48 -4
  15. data/lib/openhab/core/items/provider.rb +4 -0
  16. data/lib/openhab/core/items/registry.rb +10 -1
  17. data/lib/openhab/core/items/semantics/enumerable.rb +29 -6
  18. data/lib/openhab/core/items/state_storage.rb +2 -2
  19. data/lib/openhab/core/items.rb +6 -13
  20. data/lib/openhab/core/provider.rb +2 -2
  21. data/lib/openhab/core/proxy.rb +5 -0
  22. data/lib/openhab/core/registry.rb +12 -2
  23. data/lib/openhab/core/rules/provider.rb +0 -15
  24. data/lib/openhab/core/rules.rb +1 -1
  25. data/lib/openhab/core/script_handling.rb +8 -8
  26. data/lib/openhab/core/things/links/provider.rb +38 -0
  27. data/lib/openhab/core/things/provider.rb +4 -0
  28. data/lib/openhab/core/things/registry.rb +4 -0
  29. data/lib/openhab/core/timer.rb +3 -19
  30. data/lib/openhab/core/types/date_time_type.rb +1 -1
  31. data/lib/openhab/core/types/decimal_type.rb +4 -9
  32. data/lib/openhab/core/types/hsb_type.rb +2 -2
  33. data/lib/openhab/core/types/quantity_type.rb +4 -9
  34. data/lib/openhab/core/types/string_type.rb +1 -1
  35. data/lib/openhab/core/types/type.rb +8 -28
  36. data/lib/openhab/core/types.rb +16 -3
  37. data/lib/openhab/core.rb +3 -3
  38. data/lib/openhab/core_ext/java/duration.rb +2 -0
  39. data/lib/openhab/core_ext/java/local_date.rb +15 -7
  40. data/lib/openhab/core_ext/java/local_time.rb +13 -3
  41. data/lib/openhab/core_ext/java/month.rb +1 -1
  42. data/lib/openhab/core_ext/java/month_day.rb +13 -3
  43. data/lib/openhab/core_ext/java/period.rb +1 -1
  44. data/lib/openhab/core_ext/java/temporal_amount.rb +1 -1
  45. data/lib/openhab/core_ext/java/time.rb +5 -1
  46. data/lib/openhab/core_ext/java/zoned_date_time.rb +15 -2
  47. data/lib/openhab/core_ext/ruby/date.rb +2 -2
  48. data/lib/openhab/core_ext/ruby/{class.rb → module.rb} +3 -3
  49. data/lib/openhab/core_ext/ruby/numeric.rb +6 -1
  50. data/lib/openhab/dsl/items/builder.rb +25 -12
  51. data/lib/openhab/dsl/items/ensure.rb +8 -6
  52. data/lib/openhab/dsl/rules/automation_rule.rb +2 -23
  53. data/lib/openhab/dsl/rules/builder.rb +47 -2
  54. data/lib/openhab/dsl/rules/terse.rb +15 -13
  55. data/lib/openhab/dsl/timer_manager.rb +1 -1
  56. data/lib/openhab/dsl/version.rb +1 -1
  57. data/lib/openhab/dsl.rb +38 -11
  58. data/lib/openhab/osgi.rb +1 -3
  59. data/lib/openhab/rspec/helpers.rb +3 -5
  60. data/lib/openhab/rspec/hooks.rb +1 -0
  61. data/lib/openhab/rspec/mocks/timer.rb +33 -0
  62. data/lib/openhab/rspec.rb +9 -0
  63. metadata +23 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc3911eb787dc73ea31109aa6d4d8c3896a1019b381a70030f152c668f0b8f2e
4
- data.tar.gz: ebd2d7005e9f17827a4bf58d38b7fc2476a497cb428aab0270290c3c98461b80
3
+ metadata.gz: 8ef6b7b058463c4bbcbc500b23baf44e1ef8f3872c39f88f3819875523b9d350
4
+ data.tar.gz: f2c5511e9c61eb79a1464161d35ba239570e45172be44415784994688a789c67
5
5
  SHA512:
6
- metadata.gz: df4c1df793cd44700467728c63df6ba9d12ecf7111fc7daf2b9a8f4953c68575082f9f4b87f70a42bfedcc9af70d4537e45b6fb2d8b78ac8e7e3f7cca22aaf4b
7
- data.tar.gz: de1c8f5847bbbeb3eed3268ceedc2a61213b4f6ab269372a08bd4d8217f6b384a2c62b5ceb1f9de2777d264d0d6eb4e02fde6f245fa4fcc0dc03d068041a11bb
6
+ metadata.gz: 7b4aca0a4cb592c7bcb84c4c50772d359cfc704f4bccb31e3aa58a1e76be0e15de9276c0184bcd696aed1c05cb7361e0f4d74f892eb9347f0a43f54ac596ecdb
7
+ data.tar.gz: 1053d9bd85f8013bcfa37242f1354e333587884179f8600c4f48ad19c5d1aa8cfdbb7795a32b37147d83d1b11334cb993663e761c4a0c2cf9574b5ec1355586e
@@ -4,47 +4,47 @@ module OpenHAB
4
4
  module Core
5
5
  module Actions
6
6
  # @see https://www.openhab.org/docs/configuration/actions.html#exec-actions Exec Actions
7
- class Exec
8
- class << self # rubocop:disable Lint/EmptyClass
9
- # @!method execute_command_line
10
- #
11
- # @return [void]
12
- #
13
- # @overload execute_command_line(command_line)
14
- #
15
- # Executes a command on the command line without waiting for the
16
- # command to complete.
17
- #
18
- # @param [String] command_line
19
- # @return [void]
20
- #
21
- # @example Execute an external command
22
- # rule 'Run a command' do
23
- # every :day
24
- # run do
25
- # Exec.execute_command_line('/bin/true')
26
- # end
27
- # end
28
- #
29
- # @overload execute_command_line(timeout, command_line)
30
- #
31
- # Executes a command on the command and waits timeout seconds for
32
- # the command to complete, returning the output from the command
33
- # as a String.
34
- #
35
- # @param [Duration] timeout
36
- # @param [String] command_line
37
- # @return [String]
38
- #
39
- # @example Execute an external command and process its results
40
- # rule 'Run a command' do
41
- # every :day
42
- # run do
43
- # TodaysHoliday_String.update(Exec.execute_command_line(5.seconds, '/home/cody/determine_holiday.rb')
44
- # end
45
- # end
46
- #
47
- end
7
+ class Exec # rubocop:disable Lint/EmptyClass
8
+ # @!scope class
9
+
10
+ # @!method execute_command_line
11
+ #
12
+ # @return [void]
13
+ #
14
+ # @overload execute_command_line(command_line)
15
+ #
16
+ # Executes a command on the command line without waiting for the
17
+ # command to complete.
18
+ #
19
+ # @param [String] command_line
20
+ # @return [void]
21
+ #
22
+ # @example Execute an external command
23
+ # rule 'Run a command' do
24
+ # every :day
25
+ # run do
26
+ # Exec.execute_command_line('/bin/true')
27
+ # end
28
+ # end
29
+ #
30
+ # @overload execute_command_line(timeout, command_line)
31
+ #
32
+ # Executes a command on the command and waits timeout seconds for
33
+ # the command to complete, returning the output from the command
34
+ # as a String.
35
+ #
36
+ # @param [Duration] timeout
37
+ # @param [String] command_line
38
+ # @return [String]
39
+ #
40
+ # @example Execute an external command and process its results
41
+ # rule 'Run a command' do
42
+ # every :day
43
+ # run do
44
+ # TodaysHoliday_String.update(Exec.execute_command_line(5.seconds, '/home/cody/determine_holiday.rb')
45
+ # end
46
+ # end
47
+ #
48
48
  end
49
49
  end
50
50
  end
@@ -7,7 +7,7 @@ module OpenHAB
7
7
  class Transformation
8
8
  class << self
9
9
  # @!visibility private
10
- alias_method :transform_raw, :transform if instance_methods.include?(:say)
10
+ alias_method :raw_transform, :transform if instance_methods.include?(:transform)
11
11
 
12
12
  #
13
13
  # Applies a transformation of a given type with some function to a value.
@@ -20,10 +20,10 @@ module OpenHAB
20
20
  # @return [String] the transformed value, or the original value if an error occurred
21
21
  #
22
22
  # @example Run a transformation
23
- # Transformation.transform(:map, "myfan.map", 0)
23
+ # transform(:map, "myfan.map", 0)
24
24
  #
25
25
  def transform(type, function, value)
26
- transform_raw(type.to_s.upcase, function.to_s, value.to_s)
26
+ raw_transform(type.to_s.upcase, function.to_s, value.to_s)
27
27
  end
28
28
  end
29
29
  end
@@ -43,7 +43,7 @@ module OpenHAB
43
43
  end
44
44
 
45
45
  # Import common actions
46
- %w[Exec HTTP Ping].each do |action|
46
+ %w[Exec HTTP Ping Transformation].each do |action|
47
47
  klass = (java_import "org.openhab.core.model.script.actions.#{action}").first
48
48
  Object.const_set(action, klass)
49
49
  end
@@ -7,71 +7,71 @@ module OpenHAB
7
7
  module Events
8
8
  java_import org.openhab.core.items.events.ItemCommandEvent
9
9
 
10
- # Adds methods to core openHAB ItemCommandEvent to make it more natural in Ruby
10
+ # {AbstractEvent} sent when an item receives a command.
11
11
  class ItemCommandEvent < ItemEvent
12
12
  # @!attribute [r] command
13
13
  # @return [Command] The command sent to the item.
14
14
  alias_method :command, :item_command
15
15
 
16
16
  # @!method refresh?
17
- # Check if `self == REFRESH`
18
- # @return [true,false]
17
+ # Check if {#command} is {REFRESH}
18
+ # @return [true, false]
19
19
 
20
20
  # @!method on?
21
- # Check if `self == ON`
22
- # @return [true,false]
21
+ # Check if {#command} is (implicitly convertible to) {ON}
22
+ # @return [true, false]
23
23
 
24
24
  # @!method off?
25
- # Check if `self == OFF`
26
- # @return [true,false]
25
+ # Check if {#command} is (implicitly convertible to) {OFF}
26
+ # @return [true, false]
27
27
 
28
28
  # @!method up?
29
- # Check if `self == UP`
30
- # @return [true,false]
29
+ # Check if {#command} is (implicitly convertible to) {UP}
30
+ # @return [true, false]
31
31
 
32
32
  # @!method down?
33
- # Check if `self == DOWN`
34
- # @return [true,false]
33
+ # Check if {#command} is (implicitly convertible to) {DOWN}
34
+ # @return [true, false]
35
35
 
36
36
  # @!method stop?
37
- # Check if `self == STOP`
38
- # @return [true,false]
37
+ # Check if {#command} is {STOP}
38
+ # @return [true, false]
39
39
 
40
40
  # @!method move?
41
- # Check if `self == MOVE`
42
- # @return [true,false]
41
+ # Check if {#command} is {MOVE}
42
+ # @return [true, false]
43
43
 
44
44
  # @!method increase?
45
- # Check if `self == INCREASE`
46
- # @return [true,false]
45
+ # Check if {#command} is {INCREASE}
46
+ # @return [true, false]
47
47
 
48
48
  # @!method decrease?
49
- # Check if `self == DECREASE`
50
- # @return [true,false]
49
+ # Check if {#command} is {DECREASE}
50
+ # @return [true, false]
51
51
 
52
52
  # @!method play?
53
- # Check if `self == PLAY`
54
- # @return [true,false]
53
+ # Check if {#command} is {PLAY}
54
+ # @return [true, false]
55
55
 
56
56
  # @!method pause?
57
- # Check if `self == PAUSE`
58
- # @return [true,false]
57
+ # Check if {#command} is {PAUSE}
58
+ # @return [true, false]
59
59
 
60
60
  # @!method rewind?
61
- # Check if `self == REWIND`
62
- # @return [true,false]
61
+ # Check if {#command} is {REWIND}
62
+ # @return [true, false]
63
63
 
64
64
  # @!method fast_forward?
65
- # Check if `self == FASTFORWARD`
66
- # @return [true,false]
65
+ # Check if {#command} is {FASTFORWARD}
66
+ # @return [true, false]
67
67
 
68
68
  # @!method next?
69
- # Check if `self == NEXT`
70
- # @return [true,false]
69
+ # Check if {#command} is {NEXT}
70
+ # @return [true, false]
71
71
 
72
72
  # @!method previous?
73
- # Check if `self == PREVIOUS`
74
- # @return [true,false]
73
+ # Check if {#command} is {PREVIOUS}
74
+ # @return [true, false]
75
75
  end
76
76
  end
77
77
  end
@@ -8,32 +8,55 @@ module OpenHAB
8
8
  java_import org.openhab.core.items.events.ItemStateChangedEvent
9
9
 
10
10
  #
11
- # Adds methods to core openHAB ItemStateChangedEvent to make it more natural in Ruby
11
+ # {AbstractEvent} sent when an item's state has changed.
12
12
  #
13
13
  class ItemStateChangedEvent < ItemEvent
14
14
  include ItemState
15
15
 
16
- #
17
- # Check if state was == {UNDEF}
18
- #
19
- # @return [true,false] True if the state is {UNDEF}, false otherwise
20
- #
21
- def was_undef?
22
- old_item_state == UNDEF
23
- end
16
+ # @!method was_undef?
17
+ # Check if {#was} is {UNDEF}
18
+ # @return [true, false]
24
19
 
25
- #
26
- # Check if state was == {NULL}
27
- #
28
- # @return [true,false] True if the state is {NULL}, false otherwise
29
- def was_null?
30
- old_item_state == NULL
31
- end
20
+ # @!method was_null?
21
+ # Check if {#was} is {NULL}
22
+ # @return [true, false]
23
+
24
+ # @!method was_on?
25
+ # Check if {#was} is (implicitly convertible to) {ON}
26
+ # @return [true, false]
27
+
28
+ # @!method was_off?
29
+ # Check if {#was} is (implicitly convertible to) {OFF}
30
+ # @return [true, false]
31
+
32
+ # @!method was_up?
33
+ # Check if {#was} is (implicitly convertible to) {UP}
34
+ # @return [true, false]
35
+
36
+ # @!method was_down?
37
+ # Check if {#was} is (implicitly convertible to) {DOWN}
38
+ # @return [true, false]
39
+
40
+ # @!method was_open?
41
+ # Check if {#was} is (implicitly convertible to) {OPEN}
42
+ # @return [true, false]
43
+
44
+ # @!method was_closed?
45
+ # Check if {#was} is (implicitly convertible to) {CLOSED}
46
+ # @return [true, false]
47
+
48
+ # @!method was_playing?
49
+ # Check if {#was} is {PLAY}
50
+ # @return [true, false]
51
+
52
+ # @!method was_paused?
53
+ # Check if {#was} is {PAUSE}
54
+ # @return [true, false]
32
55
 
33
56
  #
34
57
  # Check if state was defined (not {UNDEF} or {NULL})
35
58
  #
36
- # @return [true,false] True if state is not {UNDEF} or {NULL}
59
+ # @return [true,false]
37
60
  #
38
61
  def was?
39
62
  !old_item_state.is_a?(UnDefType)
@@ -41,7 +64,7 @@ module OpenHAB
41
64
 
42
65
  #
43
66
  # @!attribute [r] was
44
- # @return [State, nil] The state of the item if it was not {UNDEF} or {NULL}, `nil` otherwise.
67
+ # @return [State, nil] the prior state of the item if it was not {UNDEF} or {NULL}, `nil` otherwise.
45
68
  #
46
69
  def was
47
70
  old_item_state if was?
@@ -5,29 +5,57 @@ module OpenHAB
5
5
  module Events
6
6
  java_import org.openhab.core.items.events.ItemStateEvent
7
7
 
8
+ #
8
9
  # Helpers common to {ItemStateEvent} and {ItemStateChangedEvent}.
10
+ #
11
+ # Methods that refer to implicit conversion mean that for example
12
+ # a PercentType of 100% will be `true` for {#on?}, etc.
13
+ #
9
14
  module ItemState
10
- #
11
- # Check if the state == {UNDEF}
12
- #
13
- # @return [true,false] True if the state is {UNDEF}, false otherwise
14
- #
15
- def undef?
16
- item_state == UNDEF
17
- end
15
+ # @!method undef?
16
+ # Check if {#state} is {UNDEF}
17
+ # @return [true, false]
18
18
 
19
- #
20
- # Check if the state == {NULL}
21
- #
22
- # @return [true,false] True if the state is {NULL}, false otherwise
23
- def null?
24
- item_state == NULL
25
- end
19
+ # @!method null?
20
+ # Check if {#state} is {NULL}
21
+ # @return [true, false]
22
+
23
+ # @!method on?
24
+ # Check if {#state} is (implicitly convertible to) {ON}
25
+ # @return [true, false]
26
+
27
+ # @!method off?
28
+ # Check if {#state} is (implicitly convertible to) {OFF}
29
+ # @return [true, false]
30
+
31
+ # @!method up?
32
+ # Check if {#state} is (implicitly convertible to) {UP}
33
+ # @return [true, false]
34
+
35
+ # @!method down?
36
+ # Check if {#state} is (implicitly convertible to) {DOWN}
37
+ # @return [true, false]
38
+
39
+ # @!method open?
40
+ # Check if {#state} is (implicitly convertible to) {OPEN}
41
+ # @return [true, false]
42
+
43
+ # @!method closed?
44
+ # Check if {#state} is (implicitly convertible to) {CLOSED}
45
+ # @return [true, false]
46
+
47
+ # @!method playing?
48
+ # Check if {#state} is {PLAY}
49
+ # @return [true, false]
50
+
51
+ # @!method paused?
52
+ # Check if {#state} is {PAUSE}
53
+ # @return [true, false]
26
54
 
27
55
  #
28
- # Check if the state is defined (not {UNDEF} or {NULL})
56
+ # Check if {#state} is defined (not {UNDEF} or {NULL})
29
57
  #
30
- # @return [true,false] True if state is not {UNDEF} or {NULL}
58
+ # @return [true, false]
31
59
  #
32
60
  def state?
33
61
  !item_state.is_a?(UnDefType)
@@ -35,7 +63,7 @@ module OpenHAB
35
63
 
36
64
  #
37
65
  # @!attribute [r] state
38
- # @return [State, nil] The state of the item if it is not {UNDEF} or {NULL}, `nil` otherwise.
66
+ # @return [State, nil] the state of the item if it is not {UNDEF} or {NULL}, `nil` otherwise.
39
67
  #
40
68
  def state
41
69
  item_state if state?
@@ -45,9 +45,10 @@ module OpenHAB
45
45
  # Time types need formatted as ISO8601
46
46
  # @!visibility private
47
47
  def format_type(command)
48
- return Types::DateTimeType.new(command) if command.is_a?(java.time.ZonedDateTime)
48
+ return command if command.is_a?(Types::DateTimeType)
49
+ return Types::DateTimeType.new(command.to_zoned_date_time) if command.respond_to?(:to_zoned_date_time)
50
+ return Types::DateTimeType.new(DSL.try_parse_time_like(command.to_str)) if command.respond_to?(:to_str)
49
51
 
50
- command = command.iso8601 if command.respond_to?(:iso8601)
51
52
  super
52
53
  end
53
54
  end
@@ -71,6 +71,34 @@ module OpenHAB
71
71
  !raw_state.is_a?(Types::UnDefType)
72
72
  end
73
73
 
74
+ # @!attribute [r] formatted_state
75
+ #
76
+ # Format the item's state according to its state description
77
+ #
78
+ # This may include running a transformation.
79
+ #
80
+ # @return [String]
81
+ #
82
+ # @example
83
+ # logger.info(Exterior_WindDirection.formatted_state) # => "NE (36°)"
84
+ #
85
+ def formatted_state
86
+ # use to_string, not to_s, to get the original openHAB toString(), instead of any overrides
87
+ # the JRuby library has defined
88
+ raw_state_string = raw_state.to_string
89
+
90
+ return raw_state_string unless (pattern = state_description&.pattern)
91
+
92
+ transformed_state_string = org.openhab.core.transform.TransformationHelper.transform(OSGi.bundle_context,
93
+ pattern,
94
+ raw_state_string)
95
+ return state.format(pattern) if transformed_state_string.nil? || transformed_state_string == raw_state_string
96
+
97
+ transformed_state_string
98
+ rescue org.openhab.core.transform.TransformationException
99
+ raw_state_string
100
+ end
101
+
74
102
  #
75
103
  # @!attribute [r] state
76
104
  # @return [State, nil]
@@ -153,7 +181,7 @@ module OpenHAB
153
181
  return state if state.is_a?(Types::State)
154
182
 
155
183
  state = state.to_s
156
- org.openhab.core.types.TypeParser.parse_state(getAcceptedDataTypes, state) || state
184
+ org.openhab.core.types.TypeParser.parse_state(getAcceptedDataTypes, state) || StringType.new(state)
157
185
  end
158
186
 
159
187
  # formats a {Types::Type} to send to the event bus
@@ -163,9 +191,99 @@ module OpenHAB
163
191
  # make sure to use Type, because this method is used for both
164
192
  # #update and #command
165
193
  return type if type.is_a?(Types::Type)
194
+ return NULL if type.nil?
166
195
 
167
196
  type.to_s
168
197
  end
198
+
199
+ #
200
+ # Defers notifying openHAB of modifications to multiple attributes until the block is complete.
201
+ #
202
+ # @param [true, false] force When true, allow modifications to file-based items.
203
+ # Normally a FrozenError is raised when attempting to modify file-based items, since
204
+ # they will then be out-of-sync with the definition on disk. Advanced users may do this
205
+ # knowingly and intentionally though, so an escape hatch is provided to allow runtime
206
+ # modifications.
207
+ # @yield
208
+ # @return [Object] the block's return value
209
+ #
210
+ # @example Modify label and tags for an item
211
+ # MySwitch.modify do
212
+ # MySwitch.label = "New Label"
213
+ # MySwitch.tags = :labeled
214
+ # end
215
+ #
216
+ def modify(force: false)
217
+ raise ArgumentError, "you must pass a block to modify" unless block_given?
218
+ return yield if instance_variable_defined?(:@modifying) && @modifying
219
+
220
+ begin
221
+ provider = self.provider
222
+ if provider && !provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
223
+ raise FrozenError, "Cannot modify item #{name} from provider #{provider.inspect}." unless force
224
+
225
+ provider = nil
226
+ logger.debug("Forcing modifications to non-managed item #{name}")
227
+ end
228
+ @modified = false
229
+ @modifying = true
230
+
231
+ r = yield
232
+
233
+ provider&.update(self) if @modified
234
+ r
235
+ ensure
236
+ @modifying = false
237
+ end
238
+ end
239
+
240
+ # @!attribute [rw] label
241
+ # The item's descriptive label.
242
+ # @return [String]
243
+ def label=(value)
244
+ modify do
245
+ next if label == value
246
+
247
+ @modified = true
248
+ set_label(value)
249
+ end
250
+ end
251
+
252
+ # @!attribute [rw] category
253
+ # The item's category.
254
+ # @return [String]
255
+ def category=(value)
256
+ modify do
257
+ value = value&.to_s
258
+ next if category == value
259
+
260
+ @modified = true
261
+ set_category(value)
262
+ end
263
+ end
264
+
265
+ # @!attribute [rw] tags
266
+ # The item's tags
267
+ # @return [Array<String>]
268
+ # @overload tags
269
+ # Returns the item's tags.
270
+ # @return [Array<String>]
271
+ # @overload tags=(values)
272
+ # Sets the item's tags.
273
+ #
274
+ # To remove all tags, assign an empty array or nil.
275
+ # @param [Array<String,Symbol,Semantics::Tag>] values Tags to set.
276
+ # @return [void]
277
+ def tags=(values)
278
+ modify do
279
+ values = DSL::Items::ItemBuilder.normalize_tags(*values)
280
+ next if values.to_set == tags.to_set
281
+
282
+ @modified = true
283
+ remove_all_tags
284
+ add_tags(values)
285
+ end
286
+ end
169
287
  end
170
288
  end
171
289
  end