2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.velux.internal.factory;
15 import java.util.HashSet;
16 import java.util.Hashtable;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.velux.internal.VeluxBindingConstants;
22 import org.openhab.binding.velux.internal.discovery.VeluxDiscoveryService;
23 import org.openhab.binding.velux.internal.handler.VeluxBindingHandler;
24 import org.openhab.binding.velux.internal.handler.VeluxBridgeHandler;
25 import org.openhab.binding.velux.internal.handler.VeluxHandler;
26 import org.openhab.binding.velux.internal.utils.Localization;
27 import org.openhab.core.config.discovery.DiscoveryService;
28 import org.openhab.core.i18n.LocaleProvider;
29 import org.openhab.core.i18n.TranslationProvider;
30 import org.openhab.core.thing.Bridge;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
34 import org.openhab.core.thing.binding.ThingHandler;
35 import org.openhab.core.thing.binding.ThingHandlerFactory;
36 import org.osgi.framework.ServiceRegistration;
37 import org.osgi.service.component.ComponentContext;
38 import org.osgi.service.component.annotations.Activate;
39 import org.osgi.service.component.annotations.Component;
40 import org.osgi.service.component.annotations.Reference;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 * The {@link VeluxHandlerFactory} is responsible for creating things and thing
48 * @author Guenther Schreiner - Initial contribution
51 @Component(service = ThingHandlerFactory.class, name = "binding.velux")
52 public class VeluxHandlerFactory extends BaseThingHandlerFactory {
53 private final Logger logger = LoggerFactory.getLogger(VeluxHandlerFactory.class);
57 private @Nullable ServiceRegistration<?> discoveryServiceRegistration = null;
58 private @Nullable VeluxDiscoveryService discoveryService = null;
60 private Set<VeluxBindingHandler> veluxBindingHandlers = new HashSet<>();
61 private Set<VeluxBridgeHandler> veluxBridgeHandlers = new HashSet<>();
62 private Set<VeluxHandler> veluxHandlers = new HashSet<>();
64 private @NonNullByDefault({}) LocaleProvider localeProvider;
65 private @NonNullByDefault({}) TranslationProvider i18nProvider;
66 private Localization localization = Localization.UNKNOWN;
68 private @Nullable static VeluxHandlerFactory activeInstance = null;
72 private void registerDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
73 logger.trace("registerDeviceDiscoveryService({}) called.", bridgeHandler);
74 VeluxDiscoveryService discoveryService = this.discoveryService;
75 if (discoveryService == null) {
76 discoveryService = this.discoveryService = new VeluxDiscoveryService(localization);
78 discoveryService.addBridge(bridgeHandler);
79 if (discoveryServiceRegistration == null) {
80 discoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(),
81 discoveryService, new Hashtable<>());
85 private synchronized void unregisterDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
86 logger.trace("unregisterDeviceDiscoveryService({}) called.", bridgeHandler);
87 VeluxDiscoveryService discoveryService = this.discoveryService;
88 if (discoveryService != null) {
89 discoveryService.removeBridge(bridgeHandler);
90 if (discoveryService.isEmpty()) {
91 ServiceRegistration<?> discoveryServiceRegistration = this.discoveryServiceRegistration;
92 if (discoveryServiceRegistration != null) {
93 discoveryServiceRegistration.unregister();
94 this.discoveryServiceRegistration = null;
100 private @Nullable ThingHandler createBindingHandler(Thing thing) {
101 logger.trace("createBindingHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
102 VeluxBindingHandler veluxBindingHandler = new VeluxBindingHandler(thing, localization);
103 veluxBindingHandlers.add(veluxBindingHandler);
104 return veluxBindingHandler;
107 private @Nullable ThingHandler createBridgeHandler(Thing thing) {
108 logger.trace("createBridgeHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
109 VeluxBridgeHandler veluxBridgeHandler = new VeluxBridgeHandler((Bridge) thing, localization);
110 veluxBridgeHandlers.add(veluxBridgeHandler);
111 registerDeviceDiscoveryService(veluxBridgeHandler);
112 return veluxBridgeHandler;
115 private @Nullable ThingHandler createThingHandler(Thing thing) {
116 logger.trace("createThingHandler({}) called for thing named '{}'.", thing.getUID(), thing.getLabel());
117 VeluxHandler veluxHandler = new VeluxHandler(thing, localization);
118 veluxHandlers.add(veluxHandler);
122 private void updateBindingState() {
123 veluxBindingHandlers.forEach((VeluxBindingHandler veluxBindingHandler) -> {
124 veluxBindingHandler.updateBindingState(veluxBridgeHandlers.size(), veluxHandlers.size());
128 @SuppressWarnings("PMD.CompareObjectsWithEquals")
129 private void updateLocalization() {
130 if (localization == Localization.UNKNOWN && localeProvider != null && i18nProvider != null) {
131 logger.trace("updateLocalization(): creating Localization based on locale={},translation={}).",
132 localeProvider, i18nProvider);
133 localization = new Localization(localeProvider, i18nProvider);
140 public VeluxHandlerFactory(final @Reference LocaleProvider givenLocaleProvider,
141 final @Reference TranslationProvider givenI18nProvider) {
142 logger.trace("VeluxHandlerFactory(locale={},translation={}) called.", givenLocaleProvider, givenI18nProvider);
143 localeProvider = givenLocaleProvider;
144 i18nProvider = givenI18nProvider;
148 protected void setLocaleProvider(final LocaleProvider givenLocaleProvider) {
149 logger.trace("setLocaleProvider(): provided locale={}.", givenLocaleProvider);
150 localeProvider = givenLocaleProvider;
151 updateLocalization();
155 protected void setTranslationProvider(TranslationProvider givenI18nProvider) {
156 logger.trace("setTranslationProvider(): provided translation={}.", givenI18nProvider);
157 i18nProvider = givenI18nProvider;
158 updateLocalization();
164 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
165 boolean result = VeluxBindingConstants.SUPPORTED_THINGS_BINDING.contains(thingTypeUID)
166 || VeluxBindingConstants.SUPPORTED_THINGS_BRIDGE.contains(thingTypeUID)
167 || VeluxBindingConstants.SUPPORTED_THINGS_ITEMS.contains(thingTypeUID);
168 logger.trace("supportsThingType({}) called and returns {}.", thingTypeUID, result);
173 protected @Nullable ThingHandler createHandler(Thing thing) {
174 ThingHandler resultHandler = null;
175 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
177 // Handle Binding creation
178 if (VeluxBindingConstants.SUPPORTED_THINGS_BINDING.contains(thingTypeUID)) {
179 resultHandler = createBindingHandler(thing);
181 // Handle Bridge creation
182 if (VeluxBindingConstants.SUPPORTED_THINGS_BRIDGE.contains(thingTypeUID)) {
183 resultHandler = createBridgeHandler(thing);
185 // Handle creation of Things behind the Bridge
186 if (VeluxBindingConstants.SUPPORTED_THINGS_ITEMS.contains(thingTypeUID)) {
187 resultHandler = createThingHandler(thing);
189 logger.warn("createHandler({}) failed: ThingHandler not found for {}.", thingTypeUID, thing.getLabel());
191 updateBindingState();
192 return resultHandler;
196 protected void removeHandler(ThingHandler thingHandler) {
197 // Handle Binding removal
198 if (thingHandler instanceof VeluxBindingHandler) {
199 logger.trace("removeHandler() removing information element '{}'.", thingHandler.toString());
200 veluxBindingHandlers.remove(thingHandler);
202 // Handle Bridge removal
203 if (thingHandler instanceof VeluxBridgeHandler) {
204 logger.trace("removeHandler() removing bridge '{}'.", thingHandler.toString());
205 veluxBridgeHandlers.remove(thingHandler);
206 unregisterDeviceDiscoveryService((VeluxBridgeHandler) thingHandler);
208 // Handle removal of Things behind the Bridge
209 if (thingHandler instanceof VeluxHandler) {
210 logger.trace("removeHandler() removing thing '{}'.", thingHandler.toString());
211 veluxHandlers.remove(thingHandler);
213 updateBindingState();
214 super.removeHandler(thingHandler);
218 protected void activate(ComponentContext componentContext) {
219 activeInstance = this;
220 super.activate(componentContext);
224 protected void deactivate(ComponentContext componentContext) {
225 activeInstance = null;
226 super.deactivate(componentContext);
229 public static void refreshBindingInfo() {
230 VeluxHandlerFactory instance = VeluxHandlerFactory.activeInstance;
231 if (instance != null) {
232 instance.updateBindingState();