]> git.basschouten.com Git - openhab-addons.git/blob
3b783a6b09e013b0af0c70634cfb2333c481ec0d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.remoteopenhab.internal;
14
15 import static org.openhab.binding.remoteopenhab.internal.RemoteopenhabBindingConstants.BINDING_ID;
16
17 import java.util.List;
18 import java.util.Map;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.CopyOnWriteArrayList;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.core.storage.StorageService;
27 import org.openhab.core.thing.binding.AbstractStorageBasedTypeProvider;
28 import org.openhab.core.thing.type.ChannelType;
29 import org.openhab.core.thing.type.ChannelTypeProvider;
30 import org.openhab.core.thing.type.ChannelTypeUID;
31 import org.openhab.core.types.StateDescription;
32 import org.osgi.service.component.annotations.Activate;
33 import org.osgi.service.component.annotations.Component;
34 import org.osgi.service.component.annotations.Deactivate;
35 import org.osgi.service.component.annotations.Reference;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Channel type provider used for all the channel types built by the binding when building dynamically the channels.
41  * One different channel type is built for each different item type found on the remote openHAB server.
42  *
43  * @author Laurent Garnier - Initial contribution
44  * @author Laurent Garnier - Use AbstractStorageBasedTypeProvider
45  */
46 @Component(service = { ChannelTypeProvider.class, RemoteopenhabChannelTypeProvider.class })
47 @NonNullByDefault
48 public class RemoteopenhabChannelTypeProvider extends AbstractStorageBasedTypeProvider {
49
50     private static final String PATTERN_CHANNEL_TYPE_ID = "item%s%d";
51     private static final Pattern PATTERN_MATCHING_CHANNEL_TYPE_ID = Pattern.compile("^item([a-zA-Z]+)([0-9]+)$");
52
53     private final Logger logger = LoggerFactory.getLogger(RemoteopenhabChannelTypeProvider.class);
54
55     private final Map<String, List<ChannelType>> channelTypesForItemTypes = new ConcurrentHashMap<>();
56
57     @Activate
58     public RemoteopenhabChannelTypeProvider(@Reference StorageService storageService) {
59         super(storageService);
60         getChannelTypes(null).forEach(ct -> {
61             Matcher matcher = PATTERN_MATCHING_CHANNEL_TYPE_ID.matcher(ct.getUID().getId());
62             if (matcher.find()) {
63                 String itemType = matcher.group(1);
64                 // Handle number with a dimension
65                 if (itemType.startsWith("Number") && !"Number".equals(itemType)) {
66                     itemType = itemType.replace("Number", "Number:");
67                 }
68                 addChannelTypeForItemType(itemType, ct);
69             } else {
70                 logger.warn("Invalid channel type ID : {}", ct.getUID().getId());
71             }
72         });
73     }
74
75     @Deactivate
76     protected void deactivate() {
77         channelTypesForItemTypes.values().forEach(l -> l.clear());
78         channelTypesForItemTypes.clear();
79     }
80
81     public @Nullable ChannelType getChannelType(String itemType, boolean readOnly, String pattern) {
82         List<ChannelType> channelTypesForItemType = channelTypesForItemTypes.get(itemType);
83         if (channelTypesForItemType != null) {
84             for (ChannelType channelType : channelTypesForItemType) {
85                 boolean channelTypeReadOnly = false;
86                 String channelTypePattern = null;
87                 StateDescription stateDescription = channelType.getState();
88                 if (stateDescription != null) {
89                     channelTypeReadOnly = stateDescription.isReadOnly();
90                     channelTypePattern = stateDescription.getPattern();
91                 }
92                 if (channelTypePattern == null) {
93                     channelTypePattern = "";
94                 }
95                 if (channelTypeReadOnly == readOnly && channelTypePattern.equals(pattern)) {
96                     return channelType;
97                 }
98             }
99         }
100         return null;
101     }
102
103     public ChannelTypeUID buildNewChannelTypeUID(String itemType) {
104         List<ChannelType> channelTypesForItemType = channelTypesForItemTypes.get(itemType);
105         int max = 0;
106         if (channelTypesForItemType != null) {
107             for (ChannelType ct : channelTypesForItemType) {
108                 Matcher matcher = PATTERN_MATCHING_CHANNEL_TYPE_ID.matcher(ct.getUID().getId());
109                 if (matcher.find()) {
110                     int nb = Integer.parseInt(matcher.group(2));
111                     if (nb > max) {
112                         max = nb;
113                     }
114                 }
115             }
116         }
117         return new ChannelTypeUID(BINDING_ID,
118                 String.format(PATTERN_CHANNEL_TYPE_ID, itemType.replace(":", ""), max + 1));
119     }
120
121     public void addChannelType(String itemType, ChannelType channelType) {
122         putChannelType(channelType);
123         addChannelTypeForItemType(itemType, channelType);
124     }
125
126     public void removeChannelType(String itemType, ChannelType channelType) {
127         removeChannelType(channelType.getUID());
128         removeChannelTypeForItemType(itemType, channelType);
129     }
130
131     private void addChannelTypeForItemType(String itemType, ChannelType channelType) {
132         logger.debug("addChannelTypeForItemType {} {}", itemType, channelType.getUID());
133         List<ChannelType> channelTypesForItemType = channelTypesForItemTypes.computeIfAbsent(itemType,
134                 type -> new CopyOnWriteArrayList<>());
135         if (channelTypesForItemType != null) {
136             channelTypesForItemType.add(channelType);
137         }
138     }
139
140     private void removeChannelTypeForItemType(String itemType, ChannelType channelType) {
141         List<ChannelType> channelTypesForItemType = channelTypesForItemTypes.get(itemType);
142         if (channelTypesForItemType != null) {
143             channelTypesForItemType.remove(channelType);
144         }
145     }
146 }