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