Skip to content

Commit

Permalink
[remoteopenhab] Use AbstractStorageBasedTypeProvider (openhab#14956)
Browse files Browse the repository at this point in the history
* [remoteopenhab] Use AbstractStorageBasedTypeProvider

Related to openhab#14954

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
Signed-off-by: Jørgen Austvik <jaustvik@acm.org>
  • Loading branch information
lolodomo authored and austvik committed Mar 27, 2024
1 parent 4f68ffb commit f01d3fb
Showing 1 changed file with 63 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<ChannelType> 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<String, List<ChannelType>> channelTypesForItemTypes = new ConcurrentHashMap<>();

@Override
public Collection<ChannelType> 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) {
Expand All @@ -80,21 +102,42 @@ public Collection<ChannelType> getChannelTypes(@Nullable Locale locale) {

public ChannelTypeUID buildNewChannelTypeUID(String itemType) {
List<ChannelType> 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<ChannelType> channelTypesForItemType = channelTypesForItemTypes.computeIfAbsent(itemType,
type -> new CopyOnWriteArrayList<>());
if (channelTypesForItemType != null) {
channelTypesForItemType.add(channelType);
}
}

public void removeChannelType(String itemType, ChannelType channelType) {
channelTypes.remove(channelType);
private void removeChannelTypeForItemType(String itemType, ChannelType channelType) {
List<ChannelType> channelTypesForItemType = channelTypesForItemTypes.get(itemType);
if (channelTypesForItemType != null) {
channelTypesForItemType.remove(channelType);
Expand Down

0 comments on commit f01d3fb

Please sign in to comment.