From f01d3fb5c39b43778bae44e6be591ce6d463ad8b Mon Sep 17 00:00:00 2001 From: lolodomo Date: Fri, 12 May 2023 20:51:36 +0200 Subject: [PATCH] [remoteopenhab] Use AbstractStorageBasedTypeProvider (#14956) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [remoteopenhab] Use AbstractStorageBasedTypeProvider Related to #14954 Signed-off-by: Laurent Garnier Signed-off-by: Jørgen Austvik --- .../RemoteopenhabChannelTypeProvider.java | 83 ++++++++++++++----- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/RemoteopenhabChannelTypeProvider.java b/bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/RemoteopenhabChannelTypeProvider.java index 822c675dd9882..3b783a6b09e01 100644 --- a/bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/RemoteopenhabChannelTypeProvider.java +++ b/bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/RemoteopenhabChannelTypeProvider.java @@ -14,46 +14,68 @@ import static org.openhab.binding.remoteopenhab.internal.RemoteopenhabBindingConstants.BINDING_ID; -import java.util.Collection; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.storage.StorageService; +import org.openhab.core.thing.binding.AbstractStorageBasedTypeProvider; import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeProvider; import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.StateDescription; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Channel type provider used for all the channel types built by the binding when building dynamically the channels. * One different channel type is built for each different item type found on the remote openHAB server. * * @author Laurent Garnier - Initial contribution + * @author Laurent Garnier - Use AbstractStorageBasedTypeProvider */ @Component(service = { ChannelTypeProvider.class, RemoteopenhabChannelTypeProvider.class }) @NonNullByDefault -public class RemoteopenhabChannelTypeProvider implements ChannelTypeProvider { - private final List channelTypes = new CopyOnWriteArrayList<>(); +public class RemoteopenhabChannelTypeProvider extends AbstractStorageBasedTypeProvider { + + private static final String PATTERN_CHANNEL_TYPE_ID = "item%s%d"; + private static final Pattern PATTERN_MATCHING_CHANNEL_TYPE_ID = Pattern.compile("^item([a-zA-Z]+)([0-9]+)$"); + + private final Logger logger = LoggerFactory.getLogger(RemoteopenhabChannelTypeProvider.class); + private final Map> channelTypesForItemTypes = new ConcurrentHashMap<>(); - @Override - public Collection getChannelTypes(@Nullable Locale locale) { - return channelTypes; + @Activate + public RemoteopenhabChannelTypeProvider(@Reference StorageService storageService) { + super(storageService); + getChannelTypes(null).forEach(ct -> { + Matcher matcher = PATTERN_MATCHING_CHANNEL_TYPE_ID.matcher(ct.getUID().getId()); + if (matcher.find()) { + String itemType = matcher.group(1); + // Handle number with a dimension + if (itemType.startsWith("Number") && !"Number".equals(itemType)) { + itemType = itemType.replace("Number", "Number:"); + } + addChannelTypeForItemType(itemType, ct); + } else { + logger.warn("Invalid channel type ID : {}", ct.getUID().getId()); + } + }); } - @Override - public @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID, @Nullable Locale locale) { - for (ChannelType channelType : channelTypes) { - if (channelType.getUID().equals(channelTypeUID)) { - return channelType; - } - } - return null; + @Deactivate + protected void deactivate() { + channelTypesForItemTypes.values().forEach(l -> l.clear()); + channelTypesForItemTypes.clear(); } public @Nullable ChannelType getChannelType(String itemType, boolean readOnly, String pattern) { @@ -80,12 +102,34 @@ public Collection getChannelTypes(@Nullable Locale locale) { public ChannelTypeUID buildNewChannelTypeUID(String itemType) { List channelTypesForItemType = channelTypesForItemTypes.get(itemType); - int nb = channelTypesForItemType == null ? 0 : channelTypesForItemType.size(); - return new ChannelTypeUID(BINDING_ID, String.format("item%s%d", itemType.replace(":", ""), nb + 1)); + int max = 0; + if (channelTypesForItemType != null) { + for (ChannelType ct : channelTypesForItemType) { + Matcher matcher = PATTERN_MATCHING_CHANNEL_TYPE_ID.matcher(ct.getUID().getId()); + if (matcher.find()) { + int nb = Integer.parseInt(matcher.group(2)); + if (nb > max) { + max = nb; + } + } + } + } + return new ChannelTypeUID(BINDING_ID, + String.format(PATTERN_CHANNEL_TYPE_ID, itemType.replace(":", ""), max + 1)); } public void addChannelType(String itemType, ChannelType channelType) { - channelTypes.add(channelType); + putChannelType(channelType); + addChannelTypeForItemType(itemType, channelType); + } + + public void removeChannelType(String itemType, ChannelType channelType) { + removeChannelType(channelType.getUID()); + removeChannelTypeForItemType(itemType, channelType); + } + + private void addChannelTypeForItemType(String itemType, ChannelType channelType) { + logger.debug("addChannelTypeForItemType {} {}", itemType, channelType.getUID()); List channelTypesForItemType = channelTypesForItemTypes.computeIfAbsent(itemType, type -> new CopyOnWriteArrayList<>()); if (channelTypesForItemType != null) { @@ -93,8 +137,7 @@ public void addChannelType(String itemType, ChannelType channelType) { } } - public void removeChannelType(String itemType, ChannelType channelType) { - channelTypes.remove(channelType); + private void removeChannelTypeForItemType(String itemType, ChannelType channelType) { List channelTypesForItemType = channelTypesForItemTypes.get(itemType); if (channelTypesForItemType != null) { channelTypesForItemType.remove(channelType);