Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

document GenericItem#label= and GenericItem#category= #174

Merged
merged 2 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,9 @@ here is a non-exhaustive list of significant departures from the original gem:
* {OpenHAB::DSL::Rules::BuilderDSL#on_load #on_load} supports delay
* Various Ephemeris methods on {ZonedDateTime}.
* {OpenHAB::DSL::Rules::BuilderDSL#dependencies} Rule dependencies
* A set of debounce/throttle guards for file-based rules: {OpenHAB::DSL::Rules::BuilderDSL#debounce_for debounce_for},
{OpenHAB::DSL::Rules::BuilderDSL#throttle_for throttle_for}, and
{OpenHAB::DSL::Rules::BuilderDSL#only_every only_every}
* And for UI rules: {OpenHAB::DSL.debounce_for debounce_for}, {OpenHAB::DSL.throttle_for throttle_for},
{OpenHAB::DSL.only_every only_every}
* A set of debounce/throttle guards for file-based rules: {OpenHAB::DSL::Rules::BuilderDSL#debounce_for debounce_for}, {OpenHAB::DSL::Rules::BuilderDSL#throttle_for throttle_for}, and {OpenHAB::DSL::Rules::BuilderDSL#only_every only_every}
* And for UI rules: {OpenHAB::DSL.debounce_for debounce_for}, {OpenHAB::DSL.throttle_for throttle_for}, {OpenHAB::DSL.only_every only_every}
* Explicitly document modifying item labels and categories (where possible), and notify openHAB of the change

### Bug Fixes

Expand Down
66 changes: 66 additions & 0 deletions lib/openhab/core/items/generic_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,72 @@ def format_type(type)

type.to_s
end

#
# Defers notifying openHAB of modifications to multiple attributes until the block is complete.
#
# @param force [true, false] force allowing modifications to file-based items.
# Normally a FrozenError is raised when attempting to modify file-based items, since
# they will then be out-of-sync with the definition on disk. Advanced users may do this
# knowingly and intentionally though, so an escape hatch is provided to allow runtime
# modifications.
# @yield
# @return [Object] the block's return value
#
# @example Modify label and tags for an item
# MySwitch.modify do
# MySwitch.label = "New Label"
# MySwitch.tag = [:labeled]
# end
#
def modify(force: false)
raise ArgumentError, "you must pass a block to modify" unless block_given?
return yield if instance_variable_defined?(:@modifying) && @modifying

begin
provider = self.provider
if provider && !provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
provider = nil
raise FrozenError, "Cannot modify item #{name} from provider #{provider.inspect}." unless force

logger.debug("Forcing modifications to non-managed item #{name}")
end
@modified = false
@modifying = true

r = yield

provider&.update(self) if @modified
r
ensure
@modifying = false
end
end

# @!attribute [rw] label
# The item's descriptive label.
# @return [String]
def label=(value)
modify do
next if label == value

@modified = true
set_label(value)
end
end

# @!attribute [rw] category
# The item's category.
# @return [String]
def category=(value)
modify do
value = value&.to_s
next if category == value

@modified = true
set_category(value)
end
end
end
end
end
Expand Down
11 changes: 6 additions & 5 deletions lib/openhab/core/items/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@ def ===(other)
# The item's name.
# @return [String]

# @!attribute [r] label
# The item's descriptive label.
# @return [String, nil]

# @!attribute [r] accepted_command_types
# @return [Array<Class>] An array of {Command}s that can be sent as commands to this item

# @!attribute [r] accepted_data_types
# @return [Array<Class>] An array of {State}s that can be sent as commands to this item

#
# The item's {#label} if one is defined, otherwise it's {#name}.
# The item's {GenericItem#label label} if one is defined, otherwise its {#name}.
#
# @return [String]
#
Expand Down Expand Up @@ -206,6 +202,11 @@ def inspect
"#{s}>"
end

# @return [org.openhab.core.common.registry.Provider]
def provider
Provider.registry.provider_for(self)
end

private

# Allows sub-classes to append additional details to the type in an inspect string
Expand Down
4 changes: 2 additions & 2 deletions lib/openhab/core/items/state_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class StateStorage < SimpleDelegator
#
# Create a StateStorage object that stores the states of the given items
#
# @param [Array<Item>] items A list of items
# @param [Item] items A list of items
#
# @return [StateStorage] A state storage object
#
# @!visibility private
def self.from_items(*items)
StateStorage.new($events.store_states(*items).to_h)
StateStorage.new($events.store_states(*items.map(&:to_java)).to_h)
end

#
Expand Down
5 changes: 5 additions & 0 deletions lib/openhab/core/proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ def self.included(klass)
# define a sub-class of EventSubscriber as a child class of the including class
klass.const_set(:EventSubscriber, Class.new(EventSubscriber))
end

# @!visibility private
def to_java
__getobj__
end
end
end
end
6 changes: 5 additions & 1 deletion lib/openhab/core/registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ class Registry
#
def provider_for(key)
elementReadLock.lock
return nil unless (element = identifierToElement[key])
if key.is_a?(org.openhab.core.common.registry.Identifiable)
element = key
else
return nil unless (element = identifierToElement[key])
end

elementToProvider[element]
ensure
Expand Down
3 changes: 0 additions & 3 deletions lib/openhab/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,6 @@ def only_every(interval, id: nil, &block)
# end # the states will be restored here
#
def store_states(*items)
items = items.flatten.map do |item|
item.respond_to?(:__getobj__) ? item.__getobj__ : item
end
states = Core::Items::StateStorage.from_items(*items)
if block_given?
yield
Expand Down
44 changes: 44 additions & 0 deletions spec/openhab/core/items/item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,50 @@
expect(Switch1).not_to eq Switch3
end

describe "#label=" do
it "calls update on the provider" do
expect(LightSwitch.provider).to receive(:update)
LightSwitch.label = "Light Switch"
end

it "doesn't call update if no change was made" do
LightSwitch.label = "Light Switch"
expect(LightSwitch.provider).not_to receive(:update)
LightSwitch.label = "Light Switch"
end

it "raises an error if the item's provider doesn't support update" do
expect(LightSwitch.provider).not_to receive(:update)
allow(LightSwitch).to receive(:provider).and_return(Object.new)
expect { LightSwitch.label = "Light Switch" }.to raise_error(FrozenError)
end

it "ignores provider check if the item doesn't yet have a provider" do
expect(LightSwitch.provider).not_to receive(:update)
allow(LightSwitch).to receive(:provider).and_return(nil)
LightSwitch.label = "Light Switch"
expect(LightSwitch.label).to eql "Light Switch"
end
end

describe "#modify" do
it "batches multiple provider update calls" do
expect(LightSwitch.provider).to receive(:update).once
LightSwitch.modify do
LightSwitch.label = "Light Switch 1"
LightSwitch.label = "Light Switch 2"
end
end

it "doesn't call update if the item's provider doesn't support it and we're forced" do
expect(LightSwitch.provider).not_to receive(:update)
allow(LightSwitch).to receive(:provider).and_return(nil)
LightSwitch.modify(force: true) do
LightSwitch.label = "Light Switch"
end
end
end

describe "entity lookup" do
it "doesn't confuse a method call with an item" do
items.build { group_item "gGroup" }
Expand Down
6 changes: 6 additions & 0 deletions spec/openhab/core/items/registry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
expect(items).not_to include("SimmerTest")
expect(items["SimmerTest"]).to be_nil
end

describe "#provider" do
it "works" do
expect(SwitchTwo.provider).to be_a OpenHAB::Core::Items::Provider
end
end
end