]> git.basschouten.com Git - openhab-addons.git/blob
aff42c6cc933ba113f72d464546df0b232615d2e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.velux.internal.factory;
14
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Hashtable;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.velux.internal.VeluxBindingConstants;
24 import org.openhab.binding.velux.internal.discovery.VeluxDiscoveryService;
25 import org.openhab.binding.velux.internal.handler.VeluxBindingHandler;
26 import org.openhab.binding.velux.internal.handler.VeluxBridgeHandler;
27 import org.openhab.binding.velux.internal.handler.VeluxHandler;
28 import org.openhab.binding.velux.internal.utils.Localization;
29 import org.openhab.core.config.discovery.DiscoveryService;
30 import org.openhab.core.i18n.LocaleProvider;
31 import org.openhab.core.i18n.TranslationProvider;
32 import org.openhab.core.thing.Bridge;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingTypeUID;
35 import org.openhab.core.thing.ThingUID;
36 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
37 import org.openhab.core.thing.binding.ThingHandler;
38 import org.openhab.core.thing.binding.ThingHandlerFactory;
39 import org.osgi.framework.ServiceRegistration;
40 import org.osgi.service.component.annotations.Activate;
41 import org.osgi.service.component.annotations.Component;
42 import org.osgi.service.component.annotations.Reference;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * The {@link VeluxHandlerFactory} is responsible for creating things and thing
48  * handlers.
49  *
50  * @author Guenther Schreiner - Initial contribution
51  */
52 @NonNullByDefault
53 @Component(service = ThingHandlerFactory.class, name = "binding.velux")
54 public class VeluxHandlerFactory extends BaseThingHandlerFactory {
55     private final Logger logger = LoggerFactory.getLogger(VeluxHandlerFactory.class);
56
57     // Class internal
58
59     private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegistrations = new HashMap<>();
60
61     private Set<VeluxBindingHandler> veluxBindingHandlers = new HashSet<>();
62     private Set<VeluxBridgeHandler> veluxBridgeHandlers = new HashSet<>();
63     private Set<VeluxHandler> veluxHandlers = new HashSet<>();
64
65     private @NonNullByDefault({}) LocaleProvider localeProvider;
66     private @NonNullByDefault({}) TranslationProvider i18nProvider;
67     private Localization localization = Localization.UNKNOWN;
68
69     // Private
70
71     private void registerDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
72         VeluxDiscoveryService discoveryService = new VeluxDiscoveryService(bridgeHandler, localization);
73         ServiceRegistration<?> discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(),
74                 discoveryService, new Hashtable<>());
75         discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), discoveryServiceReg);
76     }
77
78     // Even if the compiler tells, that the value of <remove> cannot be null, it is possible!
79     // Therefore a @SuppressWarnings("null") is needed to suppress the warning
80     @SuppressWarnings("null")
81     private synchronized void unregisterDeviceDiscoveryService(ThingUID thingUID) {
82         logger.trace("unregisterDeviceDiscoveryService({}) called.", thingUID);
83         ServiceRegistration<?> remove = discoveryServiceRegistrations.remove(thingUID);
84         if (remove != null) {
85             remove.unregister();
86         }
87     }
88
89     private @Nullable ThingHandler createBindingHandler(Thing thing) {
90         logger.trace("createBindingHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
91         VeluxBindingHandler veluxBindingHandler = new VeluxBindingHandler(thing, localization);
92         veluxBindingHandlers.add(veluxBindingHandler);
93         return veluxBindingHandler;
94     }
95
96     private @Nullable ThingHandler createBridgeHandler(Thing thing) {
97         logger.trace("createBridgeHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
98         VeluxBridgeHandler veluxBridgeHandler = new VeluxBridgeHandler((Bridge) thing, localization);
99         veluxBridgeHandlers.add(veluxBridgeHandler);
100         registerDeviceDiscoveryService(veluxBridgeHandler);
101         return veluxBridgeHandler;
102     }
103
104     private @Nullable ThingHandler createThingHandler(Thing thing) {
105         logger.trace("createThingHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
106         VeluxHandler veluxHandler = new VeluxHandler(thing, localization);
107         veluxHandlers.add(veluxHandler);
108         return veluxHandler;
109     }
110
111     private void updateBindingState() {
112         veluxBindingHandlers.forEach((VeluxBindingHandler veluxBindingHandler) -> {
113             veluxBindingHandler.updateBindingState(veluxBridgeHandlers.size(), veluxHandlers.size());
114         });
115     }
116
117     private void updateLocalization() {
118         if (localization == Localization.UNKNOWN && localeProvider != null && i18nProvider != null) {
119             logger.trace("updateLocalization(): creating Localization based on locale={},translation={}).",
120                     localeProvider, i18nProvider);
121             localization = new Localization(localeProvider, i18nProvider);
122         }
123     }
124
125     // Constructor
126
127     @Activate
128     public VeluxHandlerFactory(final @Reference LocaleProvider givenLocaleProvider,
129             final @Reference TranslationProvider givenI18nProvider) {
130         logger.trace("VeluxHandlerFactory(locale={},translation={}) called.", givenLocaleProvider, givenI18nProvider);
131         localeProvider = givenLocaleProvider;
132         i18nProvider = givenI18nProvider;
133     }
134
135     @Reference
136     protected void setLocaleProvider(final LocaleProvider givenLocaleProvider) {
137         logger.trace("setLocaleProvider(): provided locale={}.", givenLocaleProvider);
138         localeProvider = givenLocaleProvider;
139         updateLocalization();
140     }
141
142     @Reference
143     protected void setTranslationProvider(TranslationProvider givenI18nProvider) {
144         logger.trace("setTranslationProvider(): provided translation={}.", givenI18nProvider);
145         i18nProvider = givenI18nProvider;
146         updateLocalization();
147     }
148
149     // Utility methods
150
151     @Override
152     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
153         boolean result = VeluxBindingConstants.SUPPORTED_THINGS_BINDING.contains(thingTypeUID)
154                 || VeluxBindingConstants.SUPPORTED_THINGS_BRIDGE.contains(thingTypeUID)
155                 || VeluxBindingConstants.SUPPORTED_THINGS_ITEMS.contains(thingTypeUID);
156         logger.trace("supportsThingType({}) called and returns {}.", thingTypeUID, result);
157         return result;
158     }
159
160     @Override
161     protected @Nullable ThingHandler createHandler(Thing thing) {
162         ThingHandler resultHandler = null;
163         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
164
165         // Handle Binding creation
166         if (VeluxBindingConstants.SUPPORTED_THINGS_BINDING.contains(thingTypeUID)) {
167             resultHandler = createBindingHandler(thing);
168         } else
169         // Handle Bridge creation
170         if (VeluxBindingConstants.SUPPORTED_THINGS_BRIDGE.contains(thingTypeUID)) {
171             resultHandler = createBridgeHandler(thing);
172         } else
173         // Handle creation of Things behind the Bridge
174         if (VeluxBindingConstants.SUPPORTED_THINGS_ITEMS.contains(thingTypeUID)) {
175             resultHandler = createThingHandler(thing);
176         } else {
177             logger.warn("createHandler({}) failed: ThingHandler not found for {}.", thingTypeUID, thing.getLabel());
178         }
179         updateBindingState();
180         return resultHandler;
181     }
182
183     @Override
184     protected void removeHandler(ThingHandler thingHandler) {
185         // Handle Binding removal
186         if (thingHandler instanceof VeluxBindingHandler) {
187             logger.trace("removeHandler() removing information element '{}'.", thingHandler.toString());
188             veluxBindingHandlers.remove(thingHandler);
189         } else
190         // Handle Bridge removal
191         if (thingHandler instanceof VeluxBridgeHandler) {
192             logger.trace("removeHandler() removing bridge '{}'.", thingHandler.toString());
193             veluxBridgeHandlers.remove(thingHandler);
194             unregisterDeviceDiscoveryService(thingHandler.getThing().getUID());
195         } else
196         // Handle removal of Things behind the Bridge
197         if (thingHandler instanceof VeluxHandler) {
198             logger.trace("removeHandler() removing thing '{}'.", thingHandler.toString());
199             veluxHandlers.remove(thingHandler);
200         }
201         updateBindingState();
202         super.removeHandler(thingHandler);
203     }
204 }