From a3fea884ecd8427ab40e2ec3cd620a9121253a71 Mon Sep 17 00:00:00 2001 From: OBones Date: Mon, 22 Jul 2024 10:47:34 +0200 Subject: [PATCH 1/9] Move getSupportedChannelTypeUIDs and getSupportedItemTypesOfChannel to the ProfileType interface so that StateProfileType and TriggerProfileType can both take the three filter lists given by ProfileTypeBuilder Fixes #4293 Signed-off-by: Olivier Sannier (github: obones) Signed-off-by: OBones --- .../internal/profiles/StateProfileTypeImpl.java | 10 +++++++++- .../internal/profiles/TriggerProfileTypeImpl.java | 9 ++++++++- .../openhab/core/thing/profiles/ProfileType.java | 14 ++++++++++++++ .../core/thing/profiles/ProfileTypeBuilder.java | 4 ++-- .../core/thing/profiles/StateProfileType.java | 9 --------- .../core/thing/profiles/TriggerProfileType.java | 9 --------- 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java index af7b4433b95..cccac549723 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.profiles.ProfileTypeUID; import org.openhab.core.thing.profiles.StateProfileType; +import org.openhab.core.thing.type.ChannelTypeUID; /** * Default implementation of a {@link StateProfileType}. @@ -31,13 +32,15 @@ public class StateProfileTypeImpl implements StateProfileType { private final String label; private final Collection supportedItemTypes; private final Collection supportedItemTypesOfChannel; + private final Collection supportedChannelTypeUIDs; public StateProfileTypeImpl(ProfileTypeUID profileTypeUID, String label, Collection supportedItemTypes, - Collection supportedItemTypesOfChannel) { + Collection supportedItemTypesOfChannel, Collection supportedChannelTypeUIDs) { this.profileTypeUID = profileTypeUID; this.label = label; this.supportedItemTypes = Collections.unmodifiableCollection(supportedItemTypes); this.supportedItemTypesOfChannel = Collections.unmodifiableCollection(supportedItemTypesOfChannel); + this.supportedChannelTypeUIDs = Collections.unmodifiableCollection(supportedChannelTypeUIDs); } @Override @@ -45,6 +48,11 @@ public ProfileTypeUID getUID() { return profileTypeUID; } + @Override + public Collection getSupportedChannelTypeUIDs() { + return supportedChannelTypeUIDs; + } + @Override public Collection getSupportedItemTypes() { return supportedItemTypes; diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java index 89b87819063..017ea92fe60 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java @@ -31,13 +31,15 @@ public class TriggerProfileTypeImpl implements TriggerProfileType { private final ProfileTypeUID profileTypeUID; private final String label; private final Collection supportedItemTypes; + private final Collection supportedItemTypesOfChannel; private final Collection supportedChannelTypeUIDs; public TriggerProfileTypeImpl(ProfileTypeUID profileTypeUID, String label, Collection supportedItemTypes, - Collection supportedChannelTypeUIDs) { + Collection supportedItemTypesOfChannel, Collection supportedChannelTypeUIDs) { this.profileTypeUID = profileTypeUID; this.label = label; this.supportedItemTypes = Collections.unmodifiableCollection(supportedItemTypes); + this.supportedItemTypesOfChannel = Collections.unmodifiableCollection(supportedItemTypesOfChannel); this.supportedChannelTypeUIDs = Collections.unmodifiableCollection(supportedChannelTypeUIDs); } @@ -60,4 +62,9 @@ public String getLabel() { public ProfileTypeUID getUID() { return profileTypeUID; } + + @Override + public Collection getSupportedItemTypesOfChannel() { + return supportedItemTypesOfChannel; + } } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java index 00619458f8a..a8a90622b22 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java @@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.common.registry.Identifiable; +import org.openhab.core.thing.type.ChannelTypeUID; /** * Describes a profile type. @@ -31,6 +32,19 @@ public interface ProfileType extends Identifiable { */ Collection getSupportedItemTypes(); + /** + * Get a collection of ItemType names that a Channel needs to support in order to able to use this ProfileType + * + * @return a collection of supported ItemType names (an empty list means ALL types are supported) + */ + Collection getSupportedItemTypesOfChannel(); + + /** + * + * @return a collection of ChannelTypeUIDs (may be empty if all are supported). + */ + Collection getSupportedChannelTypeUIDs(); + /** * Get a human readable description. * diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileTypeBuilder.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileTypeBuilder.java index b8e4fd1767f..3a6d04b53aa 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileTypeBuilder.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileTypeBuilder.java @@ -64,7 +64,7 @@ public static ProfileTypeBuilder newState(ProfileTypeUID profi return new ProfileTypeBuilder<>(profileTypeUID, label, (leProfileTypeUID, leLabel, leSupportedItemTypes, leSupportedItemTypesOfChannel, leSupportedChannelTypeUIDs) -> new StateProfileTypeImpl(leProfileTypeUID, leLabel, - leSupportedItemTypes, leSupportedItemTypesOfChannel)); + leSupportedItemTypes, leSupportedItemTypesOfChannel, leSupportedChannelTypeUIDs)); } /** @@ -78,7 +78,7 @@ public static ProfileTypeBuilder newTrigger(ProfileTypeUID p return new ProfileTypeBuilder<>(profileTypeUID, label, (leProfileTypeUID, leLabel, leSupportedItemTypes, leSupportedItemTypesOfChannel, leSupportedChannelTypeUIDs) -> new TriggerProfileTypeImpl(leProfileTypeUID, leLabel, - leSupportedItemTypes, leSupportedChannelTypeUIDs)); + leSupportedItemTypes, leSupportedItemTypesOfChannel, leSupportedChannelTypeUIDs)); } /** diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/StateProfileType.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/StateProfileType.java index 5ef1c501140..a3989bae1ec 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/StateProfileType.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/StateProfileType.java @@ -12,8 +12,6 @@ */ package org.openhab.core.thing.profiles; -import java.util.Collection; - import org.eclipse.jdt.annotation.NonNullByDefault; /** @@ -24,11 +22,4 @@ */ @NonNullByDefault public interface StateProfileType extends ProfileType { - - /** - * Get a collection of ItemType names that a Channel needs to support in order to able to use this ProfileType - * - * @return a collection of supported ItemType names (an empty list means ALL types are supported) - */ - Collection getSupportedItemTypesOfChannel(); } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TriggerProfileType.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TriggerProfileType.java index e0f3b2d9dcf..17d1cd1f826 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TriggerProfileType.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TriggerProfileType.java @@ -12,10 +12,7 @@ */ package org.openhab.core.thing.profiles; -import java.util.Collection; - import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.core.thing.type.ChannelTypeUID; /** * Describes a {@link TriggerProfile} type. @@ -24,10 +21,4 @@ */ @NonNullByDefault public interface TriggerProfileType extends ProfileType { - - /** - * - * @return a collection of ChannelTypeUIDs (may be empty if all are supported). - */ - Collection getSupportedChannelTypeUIDs(); } From 347fbe7e98eada6259d5c48072485876715381f0 Mon Sep 17 00:00:00 2001 From: Olivier Sannier Date: Tue, 23 Jul 2024 16:31:28 +0200 Subject: [PATCH 2/9] Use getSupportedChannelTypeUIDs and getSupportedItemTypesOfChannel on all ProfileTypes Signed-off-by: OBones --- .../internal/channel/ChannelTypeResource.java | 7 +-- .../link/ItemChannelLinkResource.java | 7 +-- .../internal/profile/ProfileTypeResource.java | 44 +++++-------------- ...mChannelLinkConfigDescriptionProvider.java | 36 ++++++++++++--- .../ProfileTypeI18nLocalizationService.java | 4 +- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/channel/ChannelTypeResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/channel/ChannelTypeResource.java index 917990b3f9e..ffa71144b4e 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/channel/ChannelTypeResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/channel/ChannelTypeResource.java @@ -48,7 +48,6 @@ import org.openhab.core.thing.dto.ChannelTypeDTO; import org.openhab.core.thing.profiles.ProfileType; import org.openhab.core.thing.profiles.ProfileTypeRegistry; -import org.openhab.core.thing.profiles.TriggerProfileType; import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeRegistry; @@ -174,10 +173,8 @@ public Response getLinkableItemTypes( Set result = new HashSet<>(); for (ProfileType profileType : profileTypeRegistry.getProfileTypes()) { - if (profileType instanceof TriggerProfileType type) { - if (type.getSupportedChannelTypeUIDs().contains(ctUID)) { - result.addAll(profileType.getSupportedItemTypes()); - } + if (profileType.getSupportedChannelTypeUIDs().contains(ctUID)) { + result.addAll(profileType.getSupportedItemTypes()); } } if (result.isEmpty()) { diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java index 803ef435226..71e5e3a792f 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java @@ -236,9 +236,10 @@ public Response link(@PathParam("itemName") @Parameter(description = "itemName") } if (!(profileType.getSupportedItemTypes().isEmpty() || profileType.getSupportedItemTypes().contains(itemType)) - || !(((TriggerProfileType) profileType).getSupportedChannelTypeUIDs().isEmpty() - || ((TriggerProfileType) profileType).getSupportedChannelTypeUIDs() - .contains(channel.getChannelTypeUID()))) { + || !(profileType.getSupportedChannelTypeUIDs().isEmpty() + || profileType.getSupportedChannelTypeUIDs().contains(channel.getChannelTypeUID())) + || !(profileType.getSupportedItemTypesOfChannel().isEmpty() + || profileType.getSupportedItemTypesOfChannel().contains(itemType))) { // item or channel type not matching return Response.status(Status.BAD_REQUEST).build(); } diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java index 92ca7637555..0a1ec2102d4 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java @@ -38,8 +38,6 @@ import org.openhab.core.items.ItemUtil; import org.openhab.core.thing.profiles.ProfileType; import org.openhab.core.thing.profiles.ProfileTypeRegistry; -import org.openhab.core.thing.profiles.StateProfileType; -import org.openhab.core.thing.profiles.TriggerProfileType; import org.openhab.core.thing.profiles.dto.ProfileTypeDTO; import org.openhab.core.thing.profiles.dto.ProfileTypeDTOMapper; import org.openhab.core.thing.type.ChannelType; @@ -128,13 +126,7 @@ private Predicate matchesChannelUID(@Nullable String channelTypeUID // requested to filter against an unknown channel type -> do not return a ProfileType return t -> false; } - switch (channelType.getKind()) { - case STATE: - return t -> stateProfileMatchesProfileType(t, channelType); - case TRIGGER: - return t -> triggerProfileMatchesProfileType(t, channelType); - } - return t -> false; + return t -> profileTypeMatchesChannelType(t, channelType); } private Predicate matchesItemType(@Nullable String itemType) { @@ -151,31 +143,19 @@ private boolean profileTypeMatchesItemType(ProfileType pt, String itemType) { || supportedItemTypesOnProfileType.contains(itemType); } - private boolean triggerProfileMatchesProfileType(ProfileType profileType, ChannelType channelType) { - if (profileType instanceof TriggerProfileType triggerProfileType) { - if (triggerProfileType.getSupportedChannelTypeUIDs().isEmpty()) { - return true; - } - - if (triggerProfileType.getSupportedChannelTypeUIDs().contains(channelType.getUID())) { - return true; - } + private boolean profileTypeMatchesChannelType(ProfileType profileType, ChannelType channelType) { + if (profileType.getSupportedChannelTypeUIDs().isEmpty() + && profileType.getSupportedItemTypesOfChannel().isEmpty()) { + return true; } - return false; - } - private boolean stateProfileMatchesProfileType(ProfileType profileType, ChannelType channelType) { - if (profileType instanceof StateProfileType stateProfileType) { - if (stateProfileType.getSupportedItemTypesOfChannel().isEmpty()) { - return true; - } - - Collection supportedItemTypesOfChannelOnProfileType = stateProfileType - .getSupportedItemTypesOfChannel(); - String itemType = channelType.getItemType(); - return itemType != null - && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); + if (profileType.getSupportedChannelTypeUIDs().contains(channelType.getUID())) { + return true; } - return false; + + Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); + String itemType = channelType.getItemType(); + return itemType != null + && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); } } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java index f55aa438ab1..10c45df4748 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java @@ -29,6 +29,7 @@ import org.openhab.core.config.core.ParameterOption; import org.openhab.core.items.Item; import org.openhab.core.items.ItemRegistry; +import org.openhab.core.items.ItemUtil; import org.openhab.core.thing.Channel; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingRegistry; @@ -38,6 +39,8 @@ import org.openhab.core.thing.profiles.ProfileTypeRegistry; import org.openhab.core.thing.profiles.StateProfileType; import org.openhab.core.thing.profiles.TriggerProfileType; +import org.openhab.core.thing.type.ChannelType; +import org.openhab.core.thing.type.ChannelTypeRegistry; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -55,16 +58,19 @@ public class ItemChannelLinkConfigDescriptionProvider implements ConfigDescripti public static final String PARAM_PROFILE = "profile"; private final ProfileTypeRegistry profileTypeRegistry; + private final ChannelTypeRegistry channelTypeRegistry; private final ItemChannelLinkRegistry itemChannelLinkRegistry; private final ItemRegistry itemRegistry; private final ThingRegistry thingRegistry; @Activate public ItemChannelLinkConfigDescriptionProvider(final @Reference ProfileTypeRegistry profileTypeRegistry, // + final @Reference ChannelTypeRegistry channelTypeRegistry, // final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, // final @Reference ItemRegistry itemRegistry, // final @Reference ThingRegistry thingRegistry) { this.profileTypeRegistry = profileTypeRegistry; + this.channelTypeRegistry = channelTypeRegistry; this.itemChannelLinkRegistry = itemChannelLinkRegistry; this.itemRegistry = itemRegistry; this.thingRegistry = thingRegistry; @@ -108,10 +114,11 @@ private List getOptions(ItemChannelLink link, Item item, Channe return profileTypes.stream().filter(profileType -> { switch (channel.getKind()) { case STATE: - return profileType instanceof StateProfileType && isSupportedItemType(profileType, item); + return profileType instanceof StateProfileType && isSupportedItemType(profileType, item) + && isSupportedChannelType(profileType, channel, locale); case TRIGGER: - return profileType instanceof TriggerProfileType tpt && isSupportedItemType(profileType, item) - && isSupportedChannelType(tpt, channel); + return profileType instanceof TriggerProfileType && isSupportedItemType(profileType, item) + && isSupportedChannelType(profileType, channel, locale); default: throw new IllegalArgumentException("Unknown channel kind: " + channel.getKind()); } @@ -123,8 +130,25 @@ private boolean isSupportedItemType(ProfileType profileType, Item item) { || profileType.getSupportedItemTypes().contains(item.getType()); } - private boolean isSupportedChannelType(TriggerProfileType profileType, Channel channel) { - return profileType.getSupportedChannelTypeUIDs().isEmpty() - || profileType.getSupportedChannelTypeUIDs().contains(channel.getChannelTypeUID()); + private boolean isSupportedChannelType(ProfileType profileType, Channel channel, @Nullable Locale locale) { + if (profileType.getSupportedChannelTypeUIDs().isEmpty() + && profileType.getSupportedItemTypesOfChannel().isEmpty()) { + return true; + } + + ChannelType channelType = channelTypeRegistry.getChannelType(channel.getChannelTypeUID(), locale); + if (channelType == null) { + // requested to filter against an unknown channel type + return false; + } + + if (profileType.getSupportedChannelTypeUIDs().contains(channelType.getUID())) { + return true; + } + + Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); + String itemType = channelType.getItemType(); + return itemType != null + && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); } } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/i18n/ProfileTypeI18nLocalizationService.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/i18n/ProfileTypeI18nLocalizationService.java index a1da0812e5c..bac7209b0df 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/i18n/ProfileTypeI18nLocalizationService.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/i18n/ProfileTypeI18nLocalizationService.java @@ -52,10 +52,12 @@ public ProfileType createLocalizedProfileType(Bundle bundle, ProfileType profile if (profileType instanceof StateProfileType type) { return ProfileTypeBuilder.newState(profileTypeUID, label != null ? label : defaultLabel) .withSupportedItemTypes(profileType.getSupportedItemTypes()) - .withSupportedItemTypesOfChannel(type.getSupportedItemTypesOfChannel()).build(); + .withSupportedItemTypesOfChannel(type.getSupportedItemTypesOfChannel()) + .withSupportedChannelTypeUIDs(type.getSupportedChannelTypeUIDs()).build(); } else if (profileType instanceof TriggerProfileType type) { return ProfileTypeBuilder.newTrigger(profileTypeUID, label != null ? label : defaultLabel) .withSupportedItemTypes(profileType.getSupportedItemTypes()) + .withSupportedItemTypesOfChannel(type.getSupportedItemTypesOfChannel()) .withSupportedChannelTypeUIDs(type.getSupportedChannelTypeUIDs()).build(); } else { return profileType; From e0924406c7639d725e48f8f61b4e1199e5ba18bb Mon Sep 17 00:00:00 2001 From: OBones Date: Fri, 26 Jul 2024 14:04:49 +0200 Subject: [PATCH 3/9] Introduce getSupportedChannelKind on ProfileType so that a given profile type can tell onto which channel kind it applies, if any Signed-off-by: OBones --- .../thing/internal/profiles/StateProfileTypeImpl.java | 8 ++++++++ .../thing/internal/profiles/TriggerProfileTypeImpl.java | 8 ++++++++ .../java/org/openhab/core/thing/profiles/ProfileType.java | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java index cccac549723..c7b1a05e001 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/StateProfileTypeImpl.java @@ -16,8 +16,10 @@ import java.util.Collections; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.thing.profiles.ProfileTypeUID; import org.openhab.core.thing.profiles.StateProfileType; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelTypeUID; /** @@ -58,6 +60,12 @@ public Collection getSupportedItemTypes() { return supportedItemTypes; } + @Override + @Nullable + public ChannelKind getSupportedChannelKind() { + return ChannelKind.STATE; + } + @Override public String getLabel() { return label; diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java index 017ea92fe60..bc0b4213ea1 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TriggerProfileTypeImpl.java @@ -16,8 +16,10 @@ import java.util.Collections; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.thing.profiles.ProfileTypeUID; import org.openhab.core.thing.profiles.TriggerProfileType; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelTypeUID; /** @@ -67,4 +69,10 @@ public ProfileTypeUID getUID() { public Collection getSupportedItemTypesOfChannel() { return supportedItemTypesOfChannel; } + + @Override + @Nullable + public ChannelKind getSupportedChannelKind() { + return ChannelKind.TRIGGER; + } } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java index a8a90622b22..9dd1c68c6e3 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java @@ -15,7 +15,9 @@ import java.util.Collection; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.common.registry.Identifiable; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelTypeUID; /** @@ -45,6 +47,12 @@ public interface ProfileType extends Identifiable { */ Collection getSupportedChannelTypeUIDs(); + /** + * @return The supported ChannelKind for this profile type. If null then all channel kinds are supported + */ + @Nullable + ChannelKind getSupportedChannelKind(); + /** * Get a human readable description. * From 7d37835e2cf29f6c297b8b99935d3cd3eb9a3c15 Mon Sep 17 00:00:00 2001 From: OBones Date: Fri, 26 Jul 2024 14:06:30 +0200 Subject: [PATCH 4/9] Must check for the channel kind supported by the profile type Signed-off-by: OBones --- .../io/rest/core/internal/profile/ProfileTypeResource.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java index 0a1ec2102d4..2c3974bb8f3 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java @@ -40,6 +40,7 @@ import org.openhab.core.thing.profiles.ProfileTypeRegistry; import org.openhab.core.thing.profiles.dto.ProfileTypeDTO; import org.openhab.core.thing.profiles.dto.ProfileTypeDTOMapper; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.thing.type.ChannelTypeUID; @@ -144,6 +145,11 @@ private boolean profileTypeMatchesItemType(ProfileType pt, String itemType) { } private boolean profileTypeMatchesChannelType(ProfileType profileType, ChannelType channelType) { + @Nullable + ChannelKind supportedChannelKind = profileType.getSupportedChannelKind(); + if (supportedChannelKind != null && supportedChannelKind != channelType.getKind()) + return false; + if (profileType.getSupportedChannelTypeUIDs().isEmpty() && profileType.getSupportedItemTypesOfChannel().isEmpty()) { return true; From e3052cc21c5a7f7519f7943125144166bba683e1 Mon Sep 17 00:00:00 2001 From: OBones Date: Fri, 26 Jul 2024 15:43:45 +0200 Subject: [PATCH 5/9] Must not exit too early, both lists must be tested Signed-off-by: OBones --- .../internal/profile/ProfileTypeResource.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java index 2c3974bb8f3..b0507bfe94f 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java @@ -150,18 +150,20 @@ private boolean profileTypeMatchesChannelType(ProfileType profileType, ChannelTy if (supportedChannelKind != null && supportedChannelKind != channelType.getKind()) return false; - if (profileType.getSupportedChannelTypeUIDs().isEmpty() - && profileType.getSupportedItemTypesOfChannel().isEmpty()) { - return true; + Collection supportedChannelTypeUIDsOnProfileType = profileType.getSupportedChannelTypeUIDs(); + if (!supportedChannelTypeUIDsOnProfileType.isEmpty() + && !supportedChannelTypeUIDsOnProfileType.contains(channelType.getUID())) { + return false; } - if (profileType.getSupportedChannelTypeUIDs().contains(channelType.getUID())) { + Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); + if (supportedItemTypesOfChannelOnProfileType.isEmpty()) { return true; + } else { + @Nullable + String itemType = channelType.getItemType(); + return itemType != null + && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); } - - Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); - String itemType = channelType.getItemType(); - return itemType != null - && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); } } From 116046b534ce15fdb7ff7b6f30755cf64cb402b5 Mon Sep 17 00:00:00 2001 From: OBones Date: Fri, 26 Jul 2024 17:02:10 +0200 Subject: [PATCH 6/9] Use code similar to the one in ProfileTypeResource for better consistency Signed-off-by: OBones --- ...mChannelLinkConfigDescriptionProvider.java | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java index 10c45df4748..a9cf310f8cb 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java @@ -37,13 +37,15 @@ import org.openhab.core.thing.link.ItemChannelLinkRegistry; import org.openhab.core.thing.profiles.ProfileType; import org.openhab.core.thing.profiles.ProfileTypeRegistry; -import org.openhab.core.thing.profiles.StateProfileType; -import org.openhab.core.thing.profiles.TriggerProfileType; +import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeRegistry; +import org.openhab.core.thing.type.ChannelTypeUID; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Provider for framework config parameters on {@link ItemChannelLink}s. @@ -54,6 +56,8 @@ @NonNullByDefault public class ItemChannelLinkConfigDescriptionProvider implements ConfigDescriptionProvider { + private final Logger logger = LoggerFactory.getLogger(ItemChannelLinkConfigDescriptionProvider.class); + private static final String SCHEME = "link"; public static final String PARAM_PROFILE = "profile"; @@ -112,16 +116,7 @@ private List getOptions(ItemChannelLink link, Item item, Channe @Nullable Locale locale) { Collection profileTypes = profileTypeRegistry.getProfileTypes(locale); return profileTypes.stream().filter(profileType -> { - switch (channel.getKind()) { - case STATE: - return profileType instanceof StateProfileType && isSupportedItemType(profileType, item) - && isSupportedChannelType(profileType, channel, locale); - case TRIGGER: - return profileType instanceof TriggerProfileType && isSupportedItemType(profileType, item) - && isSupportedChannelType(profileType, channel, locale); - default: - throw new IllegalArgumentException("Unknown channel kind: " + channel.getKind()); - } + return isSupportedItemType(profileType, item) && isSupportedChannelType(profileType, channel, locale); }).map(profileType -> new ParameterOption(profileType.getUID().toString(), profileType.getLabel())).toList(); } @@ -131,24 +126,34 @@ private boolean isSupportedItemType(ProfileType profileType, Item item) { } private boolean isSupportedChannelType(ProfileType profileType, Channel channel, @Nullable Locale locale) { - if (profileType.getSupportedChannelTypeUIDs().isEmpty() - && profileType.getSupportedItemTypesOfChannel().isEmpty()) { - return true; - } + @Nullable + ChannelKind supportedChannelKind = profileType.getSupportedChannelKind(); + if (supportedChannelKind != null && supportedChannelKind != channel.getKind()) + return false; + + ChannelTypeUID channelTypeUID = channel.getChannelTypeUID(); - ChannelType channelType = channelTypeRegistry.getChannelType(channel.getChannelTypeUID(), locale); - if (channelType == null) { - // requested to filter against an unknown channel type + Collection supportedChannelTypeUIDsOnProfileType = profileType.getSupportedChannelTypeUIDs(); + if (!supportedChannelTypeUIDsOnProfileType.isEmpty() + && !supportedChannelTypeUIDsOnProfileType.contains(channelTypeUID)) { return false; } - if (profileType.getSupportedChannelTypeUIDs().contains(channelType.getUID())) { + Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); + if (supportedItemTypesOfChannelOnProfileType.isEmpty()) { return true; - } + } else { + ChannelType channelType = channelTypeRegistry.getChannelType(channelTypeUID, locale); + if (channelType == null) { + logger.error("Requested to filter against an unknown channel type: {} is not known to the registry", + channelTypeUID.toString()); + return false; + } - Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); - String itemType = channelType.getItemType(); - return itemType != null - && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); + @Nullable + String itemType = channelType.getItemType(); + return itemType != null + && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); + } } } From 86e685277ff308cbdab8ecb8e46a83281c077627 Mon Sep 17 00:00:00 2001 From: OBones Date: Fri, 26 Jul 2024 17:06:44 +0200 Subject: [PATCH 7/9] Improve the javadoc for ProfileType Signed-off-by: OBones --- .../java/org/openhab/core/thing/profiles/ProfileType.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java index 9dd1c68c6e3..5933e7a8ad0 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileType.java @@ -29,6 +29,7 @@ public interface ProfileType extends Identifiable { /** + * Get a collection of ItemType names that this profile type supports * * @return a collection of item types (may be empty if all are supported) */ @@ -42,12 +43,15 @@ public interface ProfileType extends Identifiable { Collection getSupportedItemTypesOfChannel(); /** + * Get a collection of ChannelType UIDs that this profile type supports * * @return a collection of ChannelTypeUIDs (may be empty if all are supported). */ Collection getSupportedChannelTypeUIDs(); /** + * Get the ChannelKind this profile type supports. + * * @return The supported ChannelKind for this profile type. If null then all channel kinds are supported */ @Nullable From ef03c140df17cf40d2009b05d00869a50b98ed68 Mon Sep 17 00:00:00 2001 From: OBones Date: Mon, 29 Jul 2024 15:22:56 +0200 Subject: [PATCH 8/9] Remove @Nullable on local variables Signed-off-by: OBones --- .../core/io/rest/core/internal/profile/ProfileTypeResource.java | 2 -- .../internal/link/ItemChannelLinkConfigDescriptionProvider.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java index b0507bfe94f..f39890ba061 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/profile/ProfileTypeResource.java @@ -145,7 +145,6 @@ private boolean profileTypeMatchesItemType(ProfileType pt, String itemType) { } private boolean profileTypeMatchesChannelType(ProfileType profileType, ChannelType channelType) { - @Nullable ChannelKind supportedChannelKind = profileType.getSupportedChannelKind(); if (supportedChannelKind != null && supportedChannelKind != channelType.getKind()) return false; @@ -160,7 +159,6 @@ private boolean profileTypeMatchesChannelType(ProfileType profileType, ChannelTy if (supportedItemTypesOfChannelOnProfileType.isEmpty()) { return true; } else { - @Nullable String itemType = channelType.getItemType(); return itemType != null && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java index a9cf310f8cb..86df6e41b1b 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/link/ItemChannelLinkConfigDescriptionProvider.java @@ -126,7 +126,6 @@ private boolean isSupportedItemType(ProfileType profileType, Item item) { } private boolean isSupportedChannelType(ProfileType profileType, Channel channel, @Nullable Locale locale) { - @Nullable ChannelKind supportedChannelKind = profileType.getSupportedChannelKind(); if (supportedChannelKind != null && supportedChannelKind != channel.getKind()) return false; @@ -150,7 +149,6 @@ private boolean isSupportedChannelType(ProfileType profileType, Channel channel, return false; } - @Nullable String itemType = channelType.getItemType(); return itemType != null && supportedItemTypesOfChannelOnProfileType.contains(ItemUtil.getMainItemType(itemType)); From d0130fde8b7eb9840c690980cc2a49fd8d06dafc Mon Sep 17 00:00:00 2001 From: OBones Date: Mon, 29 Jul 2024 15:33:25 +0200 Subject: [PATCH 9/9] Rewrite the link() tests for better styling and make them similar to the two other locations where ProfileType are tested for applicability Signed-off-by: OBones --- .../link/ItemChannelLinkResource.java | 68 ++++++++++++++++--- .../link/ItemChannelLinkResourceTest.java | 4 +- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java index 71e5e3a792f..55ac579a62c 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResource.java @@ -12,7 +12,9 @@ */ package org.openhab.core.io.rest.core.internal.link; +import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Stream; @@ -20,12 +22,14 @@ import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -35,6 +39,7 @@ import org.openhab.core.auth.Role; import org.openhab.core.config.core.Configuration; import org.openhab.core.io.rest.JSONResponse; +import org.openhab.core.io.rest.LocaleService; import org.openhab.core.io.rest.RESTConstants; import org.openhab.core.io.rest.RESTResource; import org.openhab.core.io.rest.Stream2JSONInputStream; @@ -58,9 +63,10 @@ import org.openhab.core.thing.link.dto.ItemChannelLinkDTO; import org.openhab.core.thing.profiles.ProfileType; import org.openhab.core.thing.profiles.ProfileTypeRegistry; -import org.openhab.core.thing.profiles.TriggerProfileType; import org.openhab.core.thing.type.ChannelKind; +import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeRegistry; +import org.openhab.core.thing.type.ChannelTypeUID; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -69,6 +75,8 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect; import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName; import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -103,6 +111,8 @@ @NonNullByDefault public class ItemChannelLinkResource implements RESTResource { + private final Logger logger = LoggerFactory.getLogger(ItemChannelLinkResource.class); + /** The URI path to this resource */ public static final String PATH_LINKS = "links"; @@ -111,18 +121,23 @@ public class ItemChannelLinkResource implements RESTResource { private final ThingRegistry thingRegistry; private final ItemRegistry itemRegistry; private final ProfileTypeRegistry profileTypeRegistry; + private final ChannelTypeRegistry channelTypeRegistry; + private final LocaleService localeService; @Activate public ItemChannelLinkResource(final @Reference ItemRegistry itemRegistry, final @Reference ThingRegistry thingRegistry, final @Reference ChannelTypeRegistry channelTypeRegistry, final @Reference ProfileTypeRegistry profileTypeRegistry, final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, - final @Reference ManagedItemChannelLinkProvider managedItemChannelLinkProvider) { + final @Reference ManagedItemChannelLinkProvider managedItemChannelLinkProvider, + final @Reference LocaleService localeService) { this.itemChannelLinkRegistry = itemChannelLinkRegistry; this.managedItemChannelLinkProvider = managedItemChannelLinkProvider; this.thingRegistry = thingRegistry; this.itemRegistry = itemRegistry; this.profileTypeRegistry = profileTypeRegistry; + this.channelTypeRegistry = channelTypeRegistry; + this.localeService = localeService; } @GET @@ -194,9 +209,14 @@ public Response getLink(@PathParam("itemName") @Parameter(description = "item na @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Content does not match the path"), @ApiResponse(responseCode = "405", description = "Link is not editable") }) - public Response link(@PathParam("itemName") @Parameter(description = "itemName") String itemName, + public Response link( + @HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @Parameter(description = "language") @Nullable String language, + @PathParam("itemName") @Parameter(description = "itemName") String itemName, @PathParam("channelUID") @Parameter(description = "channelUID") String channelUid, @Parameter(description = "link data") @Nullable ItemChannelLinkDTO bean) { + + Locale locale = localeService.getLocale(language); + Item item; try { item = itemRegistry.getItem(itemName); @@ -230,19 +250,45 @@ public Response link(@PathParam("itemName") @Parameter(description = "itemName") } ProfileType profileType = profileTypeRegistry.getProfileTypes().stream() .filter(p -> profileUid.equals(p.getUID().getAsString())).findFirst().orElse(null); - if (!(profileType instanceof TriggerProfileType)) { + + Collection supportedItemTypesOnProfileType = profileType.getSupportedItemTypes(); + if (!supportedItemTypesOnProfileType.isEmpty() && !supportedItemTypesOnProfileType.contains(itemType)) { + // item type not matching + return Response.status(Status.BAD_REQUEST).build(); + } + + ChannelKind supportedChannelKind = profileType.getSupportedChannelKind(); + if (supportedChannelKind != null && supportedChannelKind != channelKind) { // only trigger profiles are allowed return Response.status(Status.BAD_REQUEST).build(); } - if (!(profileType.getSupportedItemTypes().isEmpty() - || profileType.getSupportedItemTypes().contains(itemType)) - || !(profileType.getSupportedChannelTypeUIDs().isEmpty() - || profileType.getSupportedChannelTypeUIDs().contains(channel.getChannelTypeUID())) - || !(profileType.getSupportedItemTypesOfChannel().isEmpty() - || profileType.getSupportedItemTypesOfChannel().contains(itemType))) { - // item or channel type not matching + + ChannelTypeUID channelTypeUID = channel.getChannelTypeUID(); + + Collection supportedChannelTypeUIDsOnProfileType = profileType + .getSupportedChannelTypeUIDs(); + if (!supportedChannelTypeUIDsOnProfileType.isEmpty() + && !supportedChannelTypeUIDsOnProfileType.contains(channelTypeUID)) { + // channel type not matching return Response.status(Status.BAD_REQUEST).build(); } + + Collection supportedItemTypesOfChannelOnProfileType = profileType.getSupportedItemTypesOfChannel(); + if (!supportedItemTypesOfChannelOnProfileType.isEmpty()) { + ChannelType channelType = channelTypeRegistry.getChannelType(channelTypeUID, locale); + if (channelType == null) { + logger.error("Requested to filter against an unknown channel type: {} is not known to the registry", + channelTypeUID.toString()); + return Response.status(Status.BAD_REQUEST).build(); + } + + String channelTypeItemType = channelType.getItemType(); + if (channelTypeItemType == null || !supportedItemTypesOfChannelOnProfileType + .contains(ItemUtil.getMainItemType(channelTypeItemType))) { + // channel item type not allowed + return Response.status(Status.BAD_REQUEST).build(); + } + } } ItemChannelLink link; diff --git a/bundles/org.openhab.core.io.rest.core/src/test/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResourceTest.java b/bundles/org.openhab.core.io.rest.core/src/test/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResourceTest.java index 23ae740adbc..64d6adcd6d2 100644 --- a/bundles/org.openhab.core.io.rest.core/src/test/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResourceTest.java +++ b/bundles/org.openhab.core.io.rest.core/src/test/java/org/openhab/core/io/rest/core/internal/link/ItemChannelLinkResourceTest.java @@ -32,6 +32,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; +import org.openhab.core.io.rest.LocaleService; import org.openhab.core.items.ItemRegistry; import org.openhab.core.thing.ThingRegistry; import org.openhab.core.thing.ThingUID; @@ -58,13 +59,14 @@ public class ItemChannelLinkResourceTest { private @Mock @NonNullByDefault({}) ProfileTypeRegistry profileTypeRegistryMock; private @Mock @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistryMock; private @Mock @NonNullByDefault({}) ManagedItemChannelLinkProvider managedItemChannelLinkProviderMock; + private @Mock @NonNullByDefault({}) LocaleService localeServiceMock; private @NonNullByDefault({}) ItemChannelLinkResource itemChannelLinkResource; @BeforeEach public void setup() { itemChannelLinkResource = new ItemChannelLinkResource(itemRegistryMock, thingRegistryMock, channelTypeRegistryMock, profileTypeRegistryMock, itemChannelLinkRegistryMock, - managedItemChannelLinkProviderMock); + managedItemChannelLinkProviderMock, localeServiceMock); when(itemChannelLinkRegistryMock.removeLinksForItem(any())).thenReturn(EXPECTED_REMOVED_LINKS); when(itemChannelLinkRegistryMock.removeLinksForThing(any())).thenReturn(EXPECTED_REMOVED_LINKS); }