openhab-jrubyscripting 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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