]> git.basschouten.com Git - openhab-addons.git/blob
3e210a17931dcd44aea87f9c940e939e17f53696
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.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;
43
44 /**
45  * The {@link VeluxHandlerFactory} is responsible for creating things and thing
46  * handlers.
47  *
48  * @author Guenther Schreiner - Initial contribution
49  */
50 @NonNullByDefault
51 @Component(service = ThingHandlerFactory.class, name = "binding.velux")
52 public class VeluxHandlerFactory extends BaseThingHandlerFactory {
53     private final Logger logger = LoggerFactory.getLogger(VeluxHandlerFactory.class);
54
55     // Class internal
56
57     private @Nullable ServiceRegistration<?> discoveryServiceRegistration = null;
58     private @Nullable VeluxDiscoveryService discoveryService = null;
59
60     private Set<VeluxBindingHandler> veluxBindingHandlers = new HashSet<>();
61     private Set<VeluxBridgeHandler> veluxBridgeHandlers = new HashSet<>();
62     private Set<VeluxHandler> veluxHandlers = new HashSet<>();
63
64     private @NonNullByDefault({}) LocaleProvider localeProvider;
65     private @NonNullByDefault({}) TranslationProvider i18nProvider;
66     private Localization localization = Localization.UNKNOWN;
67
68     private @Nullable static VeluxHandlerFactory activeInstance = null;
69
70     // Private
71
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);
77         }
78         discoveryService.addBridge(bridgeHandler);
79         if (discoveryServiceRegistration == null) {
80             discoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(),
81                     discoveryService, new Hashtable<>());
82         }
83     }
84
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;
95                 }
96             }
97         }
98     }
99
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;
105     }
106
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;
113     }
114
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);
119         return veluxHandler;
120     }
121
122     private void updateBindingState() {
123         veluxBindingHandlers.forEach((VeluxBindingHandler veluxBindingHandler) -> {
124             veluxBindingHandler.updateBindingState(veluxBridgeHandlers.size(), veluxHandlers.size());
125         });
126     }
127
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);
134         }
135     }
136
137     // Constructor
138
139     @Activate
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;
145     }
146
147     @Reference
148     protected void setLocaleProvider(final LocaleProvider givenLocaleProvider) {
149         logger.trace("setLocaleProvider(): provided locale={}.", givenLocaleProvider);
150         localeProvider = givenLocaleProvider;
151         updateLocalization();
152     }
153
154     @Reference
155     protected void setTranslationProvider(TranslationProvider givenI18nProvider) {
156         logger.trace("setTranslationProvider(): provided translation={}.", givenI18nProvider);
157         i18nProvider = givenI18nProvider;
158         updateLocalization();
159     }
160
161     // Utility methods
162
163     @Override
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);
169         return result;
170     }
171
172     @Override
173     protected @Nullable ThingHandler createHandler(Thing thing) {
174         ThingHandler resultHandler = null;
175         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
176
177         // Handle Binding creation
178         if (VeluxBindingConstants.SUPPORTED_THINGS_BINDING.contains(thingTypeUID)) {
179             resultHandler = createBindingHandler(thing);
180         } else
181         // Handle Bridge creation
182         if (VeluxBindingConstants.SUPPORTED_THINGS_BRIDGE.contains(thingTypeUID)) {
183             resultHandler = createBridgeHandler(thing);
184         } else
185         // Handle creation of Things behind the Bridge
186         if (VeluxBindingConstants.SUPPORTED_THINGS_ITEMS.contains(thingTypeUID)) {
187             resultHandler = createThingHandler(thing);
188         } else {
189             logger.warn("createHandler({}) failed: ThingHandler not found for {}.", thingTypeUID, thing.getLabel());
190         }
191         updateBindingState();
192         return resultHandler;
193     }
194
195     @Override
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);
201         } else
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);
207         } else
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);
212         }
213         updateBindingState();
214         super.removeHandler(thingHandler);
215     }
216
217     @Override
218     protected void activate(ComponentContext componentContext) {
219         activeInstance = this;
220         super.activate(componentContext);
221     }
222
223     @Override
224     protected void deactivate(ComponentContext componentContext) {
225         activeInstance = null;
226         super.deactivate(componentContext);
227     }
228
229     public static void refreshBindingInfo() {
230         VeluxHandlerFactory instance = VeluxHandlerFactory.activeInstance;
231         if (instance != null) {
232             instance.updateBindingState();
233         }
234     }
235 }