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,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openhab/core/lazy_array"
4
+
5
+ require_relative "generic_item"
6
+
7
+ module OpenHAB
8
+ module Core
9
+ module Items
10
+ java_import org.openhab.core.items.GroupItem
11
+
12
+ #
13
+ # A group behaves like a regular item, but also has {#members} which are
14
+ # nested items that can be enumerated.
15
+ #
16
+ # If the group has a particular type, the methods from that type are
17
+ # directly available.
18
+ #
19
+ #
20
+ # The examples all assume the following items exist.
21
+ # ```xtend
22
+ # Group House
23
+ # // Location perspective
24
+ # Group GroundFloor (House)
25
+ # Group Livingroom (GroundFloor)
26
+ # // Functional perspective
27
+ # Group Sensors (House)
28
+ # Group Temperatures (Sensors)
29
+ #
30
+ # Number Livingroom_Temperature "Living Room temperature" (Livingroom, Temperatures)
31
+ # Number Bedroom_Temp "Bedroom temperature" (GroundFloor, Temperatures)
32
+ # Number Den_Temp "Den temperature" (GroundFloor, Temperatures)
33
+ # ```
34
+ #
35
+ # @!attribute [r] base_item
36
+ # @return [GenericItem, nil] A typed item if the group has a particular type.
37
+ #
38
+ # @example Operate on items in a group using enumerable methods
39
+ # logger.info("Total Temperatures: #{Temperatures.members.count}")
40
+ # # Total Temperatures: 3
41
+ # logger.info("Temperatures: #{House.members.map(&:name).sort.join(', ')}")
42
+ # # Temperatures: GroundFloor, Sensors
43
+ #
44
+ # @example Access to the methods and attributes like any item
45
+ # logger.info("Group: #{Temperatures.name}" # Group: Temperatures'
46
+ #
47
+ # @example Operates on items in nested groups using enumerable methods
48
+ # logger.info("House Count: #{House.all_members.count}")
49
+ # # House Count: 7
50
+ # logger.info("Items: #{House.all_members.grep_v(GroupItem).map(&:label).sort.join(', ')}")
51
+ # # Items: Bedroom temperature, Den temperature, Living Room temperature
52
+ #
53
+ # @example Iterate through the direct members of the group
54
+ # Temperatures.members.each do |item|
55
+ # logger.info("#{item.label} is: #{item.state}")
56
+ # end
57
+ # # Living Room temperature is 22
58
+ # # Bedroom temperature is 21
59
+ # # Den temperature is 19
60
+ #
61
+ # @example
62
+ # rule 'Turn off any switch that changes' do
63
+ # changed Switches.members
64
+ # triggered(&:off)
65
+ # end
66
+ #
67
+ # @example Built in {Enumerable} functions can be applied to groups.
68
+ # logger.info("Max is #{Temperatures.members.map(&:state).max}")
69
+ # logger.info("Min is #{Temperatures.members.map(&:state).min}")
70
+ #
71
+ class GroupItem < GenericItem
72
+ #
73
+ # Class for indicating to triggers that a group trigger should be used
74
+ #
75
+ class Members
76
+ include LazyArray
77
+
78
+ # @return [GroupItem]
79
+ attr_reader :group
80
+
81
+ # @!visibility private
82
+ def initialize(group_item)
83
+ @group = group_item
84
+ end
85
+
86
+ # Explicit conversion to Array
87
+ #
88
+ # @return [Array]
89
+ def to_a
90
+ group.get_members.map { |i| Proxy.new(i) }
91
+ end
92
+
93
+ # Name of the group
94
+ #
95
+ # @return [String]
96
+ def name
97
+ group.name
98
+ end
99
+
100
+ # @return [String]
101
+ def inspect
102
+ "#<OpenHAB::Core::Items::GroupItems::Members #{name} #{map(&:name).inspect}>"
103
+ end
104
+ alias_method :to_s, :inspect
105
+ end
106
+
107
+ # Override because we want to send them to the base item if possible
108
+ %i[command update].each do |method|
109
+ define_method(method) do |command|
110
+ return base_item.__send__(method, command) if base_item
111
+
112
+ super(command)
113
+ end
114
+ end
115
+
116
+ #
117
+ # @!attribute [r] members
118
+ # @return [Members] Get an Array-like object representing the members of the group
119
+ #
120
+ # @see Enumerable
121
+ #
122
+ def members
123
+ Members.new(self)
124
+ end
125
+
126
+ #
127
+ # @!attribute [r] all_members
128
+ # @return [Array] Get all non-group members of the group recursively.
129
+ #
130
+ # @see Enumerable
131
+ #
132
+ def all_members
133
+ getAllMembers.map { |m| Proxy.new(m) }
134
+ end
135
+
136
+ # give the base item type a chance to format commands
137
+ # @!visibility private
138
+ def format_type(command)
139
+ return super unless base_item
140
+
141
+ base_item.format_type(command)
142
+ end
143
+
144
+ private
145
+
146
+ # Add base type and function details
147
+ def type_details
148
+ r = ""
149
+ r += ":#{base_item.type}#{base_item.__send__(:type_details)}" if base_item
150
+ if function && (fn = function.class.java_class.simple_name.upcase) != "EQUALITY"
151
+ r += ":#{fn}"
152
+ r += "(#{function.parameters.map(&:inspect).join(",")})" unless function.parameters.empty?
153
+ end
154
+ r
155
+ end
156
+
157
+ # Delegate missing methods to {base_item} if possible
158
+ def method_missing(method, *args, &block)
159
+ return base_item.__send__(method, *args, &block) if base_item&.respond_to?(method) # rubocop:disable Lint/RedundantSafeNavigation nil responds to :to_a
160
+
161
+ super
162
+ end
163
+
164
+ def respond_to_missing?(method, include_private = false)
165
+ return true if base_item&.respond_to?(method) # rubocop:disable Lint/RedundantSafeNavigation
166
+
167
+ super
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ # @!parse GroupItem = OpenHAB::Core::Items::GroupItem
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "pathname"
5
+ require "net/http"
6
+ require "marcel"
7
+
8
+ require_relative "generic_item"
9
+
10
+ module OpenHAB
11
+ module Core
12
+ module Items
13
+ java_import org.openhab.core.library.items.ImageItem
14
+
15
+ #
16
+ # An {ImageItem} holds the binary image data as its state.
17
+ #
18
+ # @!attribute [r] state
19
+ # @return [RawType, nil]
20
+ #
21
+ # @example Update from a base 64 encode image string
22
+ # Image.update("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=")
23
+ #
24
+ # @example Update from image bytes and mime type
25
+ # Image.update_from_bytes(File.binread(File.join(Dir.tmpdir,'1x1.png')), mime_type: 'image/png')
26
+ #
27
+ # @example Update from URL
28
+ # Image.update_from_url('https://raw.githubusercontent.com/boc-tothefuture/openhab-jruby/main/features/assets/1x1.png')
29
+ #
30
+ # @example Update from File
31
+ # Image.update_from_file('/tmp/1x1.png')
32
+ #
33
+ # @example Log image data
34
+ # logger.info("Mime type: #{Image.state.mime_type}")
35
+ # logger.info("Number of bytes: #{Image.state.bytes.length}")
36
+ #
37
+ class ImageItem < GenericItem
38
+ #
39
+ # Update image from file
40
+ #
41
+ # @param [String] file location
42
+ # @param [String] mime_type of image
43
+ #
44
+ #
45
+ def update_from_file(file, mime_type: nil)
46
+ file_data = File.binread(file)
47
+ mime_type ||= Marcel::MimeType.for(Pathname.new(file)) || Marcel::MimeType.for(file_data)
48
+ update_from_bytes(file_data, mime_type: mime_type)
49
+ end
50
+
51
+ #
52
+ # Update image from image at URL
53
+ #
54
+ # @param [String] uri location of image
55
+ #
56
+ #
57
+ def update_from_url(uri)
58
+ logger.trace("Downloading image from #{uri}")
59
+ response = Net::HTTP.get_response(URI(uri))
60
+ mime_type = response["content-type"]
61
+ bytes = response.body
62
+ mime_type ||= detect_mime_from_bytes(bytes: bytes)
63
+ update_from_bytes(bytes, mime_type: mime_type)
64
+ end
65
+
66
+ #
67
+ # Update image from image bytes
68
+ #
69
+ # @param [String] mime_type of image
70
+ # @param [Object] bytes image data
71
+ #
72
+ #
73
+ def update_from_bytes(bytes, mime_type: nil)
74
+ mime_type ||= detect_mime_from_bytes(bytes: bytes)
75
+ base_64_image = encode_image(mime_type: mime_type, bytes: bytes)
76
+ update(base_64_image)
77
+ end
78
+
79
+ private
80
+
81
+ #
82
+ # Encode image information in the format required by OpenHAB
83
+ #
84
+ # @param [String] mime_type for image
85
+ # @param [Object] bytes image data
86
+ #
87
+ # @return [String] OpenHAB image format with image data Base64 encoded
88
+ #
89
+ def encode_image(mime_type:, bytes:)
90
+ "data:#{mime_type};base64,#{Base64.strict_encode64(bytes)}"
91
+ end
92
+
93
+ #
94
+ # Detect the mime type based on bytes
95
+ #
96
+ # @param [Array] bytes representing image data
97
+ #
98
+ # @return [String] mime type if it can be detected, nil otherwise
99
+ #
100
+ def detect_mime_from_bytes(bytes:)
101
+ logger.trace("Detecting mime type from file image contents")
102
+ Marcel::MimeType.for(bytes)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # @!parse ImageItem = OpenHAB::Core::Items::ImageItem
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "generic_item"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Items
8
+ java_import org.openhab.core.library.items.LocationItem
9
+
10
+ #
11
+ # A LocationItem can be used to store GPS related information, addresses
12
+ # etc.
13
+ #
14
+ # This is useful for location awareness related functions
15
+ #
16
+ # @!attribute [r] state
17
+ # @return [PointType, nil]
18
+ #
19
+ # @example Send point commands
20
+ # Location << '30,20' # latitude of 30, longitude of 20
21
+ # Location << '30,20,80' # latitude of 30, longitude of 20, altitude of 80
22
+ # Location << PointType.new('40,20')
23
+ #
24
+ # @example Determine the distance between two locations
25
+ # logger.info "Distance from Location 1 to Location 2: #{Location1.state - Location2.state}"
26
+ # logger.info "Distance from Location 1 to Location 2: #{Location1.state - PointType.new('40,20')}"
27
+ #
28
+ class LocationItem < GenericItem
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # @!parse LocationItem = OpenHAB::Core::Items::LocationItem
@@ -0,0 +1,390 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ module Items
8
+ module Metadata
9
+ #
10
+ # {Hash} represents the configuration for a single metadata namespace.
11
+ #
12
+ # It implements the entire interface of {::Hash}.
13
+ #
14
+ # All keys are converted to strings.
15
+ #
16
+ # @!attribute [rw] value
17
+ # @return [String] The main value for the metadata namespace.
18
+ #
19
+ class Hash
20
+ java_import org.openhab.core.items.Metadata
21
+ private_constant :Metadata
22
+
23
+ include Enumerable
24
+
25
+ extend Forwardable
26
+ def_delegators :@metadata, :configuration, :hash, :to_s, :uid, :value
27
+ protected :configuration
28
+
29
+ # @!method to_hash
30
+ # Implicit conversion to {::Hash}.
31
+ # @return [::Hash]
32
+
33
+ # Make it act like a Hash; some methods can be handled by
34
+ # java.util.Map, others we have to convert to a Ruby Hash first, and
35
+ # still others (mutators) must be manually implemented below.
36
+ def_delegators :configuration,
37
+ :any?,
38
+ :default,
39
+ :default_proc,
40
+ :each,
41
+ :each_key,
42
+ :each_pair,
43
+ :each_value,
44
+ :empty?,
45
+ :filter,
46
+ :flatten,
47
+ :has_value?,
48
+ :keys,
49
+ :length,
50
+ :rassoc,
51
+ :reject,
52
+ :select,
53
+ :shift,
54
+ :size,
55
+ :to_a,
56
+ :to_h,
57
+ :to_hash,
58
+ :value?
59
+ def_delegators :to_h, :invert, :merge, :transform_keys, :transform_values
60
+
61
+ class << self
62
+ # @!visibility private
63
+ def from_item(item_name, namespace, value)
64
+ namespace = namespace.to_s
65
+ value = case value
66
+ when Hash
67
+ return value if value.uid.item_name == item_name && value.uid.namespace == namespace
68
+
69
+ [value.value, value.send(:configuration)]
70
+ when Array
71
+ raise ArgumentError, "Array must contain 2 elements: value, config" if value.length != 2
72
+
73
+ [value.first, (value.last || {}).transform_keys(&:to_s)]
74
+ when ::Hash then ["", value.transform_keys(&:to_s)]
75
+ else [value, {}]
76
+ end
77
+ new(Metadata.new(org.openhab.core.items.MetadataKey.new(namespace.to_s, item_name), *value))
78
+ end
79
+
80
+ # @!visibility private
81
+ def from_value(namespace, value)
82
+ from_item("-", namespace, value)
83
+ end
84
+ end
85
+
86
+ # @!visibility private
87
+ def initialize(metadata)
88
+ @metadata = metadata
89
+ end
90
+
91
+ # @!visibility private
92
+ def dup
93
+ new(Metadata.new(org.openhab.core.items.MetadataKey.new(uid.namespace, "-"), value, configuration))
94
+ end
95
+
96
+ # Is this object attached to an actual Item?
97
+ # @return [true,false]
98
+ def attached?
99
+ uid.item_name != "-"
100
+ end
101
+
102
+ # @!attribute [r] item
103
+ # @return [GenericItem, nil] The item this namespace is attached to.
104
+ def item
105
+ return nil unless attached?
106
+
107
+ DSL.items[uid.item_name]
108
+ end
109
+
110
+ # @!visibility private
111
+ def create
112
+ NamespaceHash.registry.add(@metadata) if attached?
113
+ end
114
+
115
+ # @!visibility private
116
+ def commit
117
+ NamespaceHash.registry.update(@metadata) if attached?
118
+ end
119
+
120
+ # @!visibility private
121
+ def eql?(other)
122
+ return true if equal?(other)
123
+ return false unless other.is_a?(Hash)
124
+ return false unless value == other.value
125
+
126
+ configuration == other.configuration
127
+ end
128
+
129
+ #
130
+ # Set the metadata value
131
+ #
132
+ def value=(value)
133
+ @metadata = org.openhab.core.items.Metadata.new(uid, value.to_s, configuration)
134
+ commit
135
+ end
136
+
137
+ # @!visibility private
138
+ def <(other)
139
+ if other.is_a?(Hash)
140
+ return false if attached? && uid == other.uid
141
+ return false unless value == other.value
142
+ end
143
+
144
+ to_h < other
145
+ end
146
+
147
+ # @!visibility private
148
+ def <=(other)
149
+ if other.is_a?(Hash)
150
+ return true if attached? && uid == other.uid
151
+ return false unless value == other.value
152
+ end
153
+
154
+ to_h <= other
155
+ end
156
+
157
+ # @!visibility private
158
+ def ==(other)
159
+ if other.is_a?(Hash)
160
+ return false unless value == other.value
161
+
162
+ return configuration == other.configuration
163
+ elsif value.empty? && other.respond_to?(:to_hash)
164
+ return configuration.to_h == other.to_hash
165
+ end
166
+ false
167
+ end
168
+
169
+ # @!visibility private
170
+ def >(other)
171
+ if other.is_a?(Hash)
172
+ return false if attached? && uid == other.uid
173
+ return false unless value == other.value
174
+ end
175
+
176
+ to_h > other
177
+ end
178
+
179
+ # @!visibility private
180
+ def >=(other)
181
+ if other.is_a?(Hash)
182
+ return true if attached? && uid == other.uid
183
+ return false unless value == other.value
184
+ end
185
+
186
+ to_h >= other
187
+ end
188
+
189
+ # @!visibility private
190
+ def [](key)
191
+ configuration[key.to_s]
192
+ end
193
+
194
+ # @!visibility private
195
+ def []=(key, value)
196
+ key = key.to_s
197
+ new_config = to_h
198
+ new_config[key] = value
199
+ replace(new_config)
200
+ value # rubocop:disable Lint/Void
201
+ end
202
+ alias_method :store, :[]=
203
+
204
+ # @!visibility private
205
+ def assoc(key)
206
+ configuration.assoc(key.to_s)
207
+ end
208
+
209
+ # @!visibility private
210
+ def clear
211
+ replace({})
212
+ end
213
+
214
+ # @!visibility private
215
+ alias_method :compact, :to_h
216
+
217
+ # @!visibility private
218
+ def compact!
219
+ # no action; impossible to have nil keys
220
+ self
221
+ end
222
+
223
+ # @!visibility private
224
+ def compare_by_identity
225
+ raise NotImplementedError
226
+ end
227
+
228
+ # @!visibility private
229
+ def compare_by_identity?
230
+ false
231
+ end
232
+
233
+ # @!visibility private
234
+ def deconstruct_keys
235
+ self
236
+ end
237
+
238
+ # @!visibility private
239
+ def default=(*)
240
+ raise NotImplementedError
241
+ end
242
+
243
+ # @!visibility private
244
+ def default_proc=(*)
245
+ raise NotImplementedError
246
+ end
247
+
248
+ # @!visibility private
249
+ def delete(key)
250
+ key = key.to_s
251
+ new_config = to_h
252
+ return yield(key) if block_given? && !new_config.key?(key)
253
+
254
+ old_value = new_config.delete(key)
255
+ replace(new_config)
256
+ old_value
257
+ end
258
+
259
+ # @!visibility private
260
+ def delete_if(&block)
261
+ raise NotImplementedError unless block
262
+
263
+ replace(to_h.delete_if(block))
264
+ end
265
+
266
+ # @!visibility private
267
+ def dig(key, *keys)
268
+ configuration.dig(key.to_s, *keys)
269
+ end
270
+
271
+ # @!visibility private
272
+ def except(*keys)
273
+ to_h.except(*keys.map(&:to_s))
274
+ end
275
+
276
+ # @!visibility private
277
+ def fetch(key, &block)
278
+ configuration.fetch(key.to_s, &block)
279
+ end
280
+
281
+ # @!visibility private
282
+ def fetch_values(*keys, &block)
283
+ configuration.fetch_values(*keys.map(&:to_s), &block)
284
+ end
285
+
286
+ # @!visibility private
287
+ def keep_if(&block)
288
+ select!(&block)
289
+ self
290
+ end
291
+
292
+ # @!visibility private
293
+ def key(value)
294
+ rassoc(value)&.first
295
+ end
296
+
297
+ # @!visibility private
298
+ def key?(key)
299
+ configuration.key?(key.to_s)
300
+ end
301
+ alias_method :include?, :key?
302
+ alias_method :has_key?, :key?
303
+ alias_method :member?, :key?
304
+
305
+ # @!visibility private
306
+ def merge!(*others, &block)
307
+ return self if others.empty?
308
+
309
+ new_config = to_h
310
+ others.each do |h|
311
+ new_config.merge!(h.transform_keys(&:to_s), &block)
312
+ end
313
+ replace(new_config)
314
+ end
315
+ alias_method :update, :merge!
316
+
317
+ # @!visibility private
318
+ def reject!(&block)
319
+ raise NotImplementedError unless block
320
+
321
+ r = to_h.reject!(&block)
322
+ replace(r) if r
323
+ end
324
+
325
+ #
326
+ # Replace the configuration with a new {::Hash}.
327
+ #
328
+ # @param [::Hash] new_config
329
+ # @return [self]
330
+ #
331
+ def replace(new_config)
332
+ @metadata = org.openhab.core.items.Metadata.new(uid, value, new_config.transform_keys(&:to_s))
333
+ commit
334
+ self
335
+ end
336
+
337
+ # @!visibility private
338
+ def select!(&block)
339
+ raise NotImplementedError unless block?
340
+
341
+ r = to_h.select!(&block)
342
+ replace(r) if r
343
+ end
344
+ alias_method :filter!, :select!
345
+
346
+ # @!visibility private
347
+ def slice(*keys)
348
+ to_h.slice(*keys.map(&:to_s))
349
+ end
350
+
351
+ # @!visibility private
352
+ def to_proc
353
+ ->(k) { self[k] }
354
+ end
355
+
356
+ # @!visibility private
357
+ def transform_keys!(*args, &block)
358
+ replace(transform_keys(*args, &block))
359
+ end
360
+
361
+ # @!visibility private
362
+ def transform_values!(&block)
363
+ raise NotImplementedError unless block
364
+
365
+ replace(transform_values(&block))
366
+ end
367
+
368
+ # @!visibility private
369
+ def values
370
+ configuration.values.to_a
371
+ end
372
+
373
+ # @!visibility private
374
+ def values_at(*keys)
375
+ configuration.values_at(*keys.map(&:to_s))
376
+ end
377
+
378
+ # @!visibility private
379
+ def inspect
380
+ return to_h.inspect if value.empty?
381
+ return value.inspect if configuration.empty?
382
+
383
+ [value, to_h].inspect
384
+ end
385
+ alias_method :to_s, :inspect
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end