Add ManagedProviders to UIRegistry (#2617)
* UIRegistry now extensible, like other Registries Signed-off-by: Jonathan Gilbert <jpg@trillica.com> * Fix comments and more Signed-off-by: Wouter Born <github@maindrain.net> Co-authored-by: Wouter Born <github@maindrain.net>pull/2934/head
parent
89bc6592da
commit
1bd70ef909
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.core.ui.internal.components;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.common.registry.ManagedProvider;
|
||||||
|
import org.openhab.core.common.registry.Provider;
|
||||||
|
import org.openhab.core.storage.StorageService;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A managed page provider which uses storage layer to keep defined pages.
|
||||||
|
*
|
||||||
|
* @author Łukasz Dywicki - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = { Provider.class, ManagedProvider.class, UIProvider.class })
|
||||||
|
public class ManagedPageProvider extends UIComponentProvider {
|
||||||
|
@Activate
|
||||||
|
public ManagedPageProvider(@Reference StorageService storageService) {
|
||||||
|
super("ui:page", storageService);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.core.ui.internal.components;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.common.registry.ManagedProvider;
|
||||||
|
import org.openhab.core.common.registry.Provider;
|
||||||
|
import org.openhab.core.storage.StorageService;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A managed widget provider which stores their definition in storage layer.
|
||||||
|
*
|
||||||
|
* @author Łukasz Dywicki - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(service = { Provider.class, ManagedProvider.class, UIProvider.class })
|
||||||
|
public class ManagedWidgetProvider extends UIComponentProvider {
|
||||||
|
@Activate
|
||||||
|
public ManagedWidgetProvider(@Reference StorageService storageService) {
|
||||||
|
super("ui:widget", storageService);
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ import org.openhab.core.ui.components.RootUIComponent;
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class UIComponentProvider extends AbstractProvider<RootUIComponent>
|
public class UIComponentProvider extends AbstractProvider<RootUIComponent>
|
||||||
implements ManagedProvider<RootUIComponent, String> {
|
implements ManagedProvider<RootUIComponent, String>, UIProvider {
|
||||||
|
|
||||||
private String namespace;
|
private String namespace;
|
||||||
private volatile Storage<RootUIComponent> storage;
|
private volatile Storage<RootUIComponent> storage;
|
||||||
|
@ -107,4 +107,9 @@ public class UIComponentProvider extends AbstractProvider<RootUIComponent>
|
||||||
}
|
}
|
||||||
return storage.get(key);
|
return storage.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNamespace() {
|
||||||
|
return namespace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,34 +12,90 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.ui.internal.components;
|
package org.openhab.core.ui.internal.components;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.openhab.core.storage.StorageService;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.common.registry.ManagedProvider;
|
||||||
|
import org.openhab.core.ui.components.RootUIComponent;
|
||||||
import org.openhab.core.ui.components.UIComponentRegistryFactory;
|
import org.openhab.core.ui.components.UIComponentRegistryFactory;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||||
|
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for a {@link UIComponentRegistryFactory} using a {@link StorageService} and a
|
* Implementation for a {@link UIComponentRegistryFactory} using a set of {@link UIComponentProvider}.
|
||||||
* {@link UIComponentProvider}.
|
|
||||||
*
|
*
|
||||||
* @author Yannick Schaus - Initial contribution
|
* @author Yannick Schaus - Initial contribution
|
||||||
|
* @author Łukasz Dywicki - Removed explicit dependency on storage providers.
|
||||||
|
* @author Jonathan Gilbert - Made providers' collections immutable.
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = UIComponentRegistryFactory.class, immediate = true)
|
@Component(service = UIComponentRegistryFactory.class, immediate = true)
|
||||||
public class UIComponentRegistryFactoryImpl implements UIComponentRegistryFactory {
|
public class UIComponentRegistryFactoryImpl implements UIComponentRegistryFactory {
|
||||||
Map<String, UIComponentRegistryImpl> registries = new HashMap<>();
|
Map<String, UIComponentRegistryImpl> registries = new ConcurrentHashMap<>();
|
||||||
|
Map<String, Set<UIProvider>> providers = new ConcurrentHashMap<>();
|
||||||
@Reference
|
|
||||||
StorageService storageService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UIComponentRegistryImpl getRegistry(String namespace) {
|
public UIComponentRegistryImpl getRegistry(String namespace) {
|
||||||
UIComponentRegistryImpl registry = registries.get(namespace);
|
UIComponentRegistryImpl registry = registries.get(namespace);
|
||||||
if (registry == null) {
|
if (registry == null) {
|
||||||
registry = new UIComponentRegistryImpl(namespace, storageService);
|
Set<UIProvider> namespaceProviders = this.providers.get(namespace);
|
||||||
|
ManagedProvider<RootUIComponent, String> managedProvider = null;
|
||||||
|
if (namespaceProviders != null) {
|
||||||
|
for (UIProvider provider : namespaceProviders) {
|
||||||
|
if (provider instanceof ManagedProvider) {
|
||||||
|
managedProvider = (ManagedProvider<RootUIComponent, String>) provider;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registry = new UIComponentRegistryImpl(namespace, managedProvider, namespaceProviders);
|
||||||
registries.put(namespace, registry);
|
registries.put(namespace, registry);
|
||||||
}
|
}
|
||||||
return registry;
|
return registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
|
||||||
|
void addProvider(UIProvider provider) {
|
||||||
|
UIComponentRegistryImpl registry = registries.get(provider.getNamespace());
|
||||||
|
if (registry != null) {
|
||||||
|
registry.addProvider(provider);
|
||||||
|
}
|
||||||
|
registerProvider(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeProvider(UIProvider provider) {
|
||||||
|
UIComponentRegistryImpl registry = registries.get(provider.getNamespace());
|
||||||
|
if (registry != null) {
|
||||||
|
registry.removeProvider(provider);
|
||||||
|
}
|
||||||
|
deregisterProvider(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerProvider(UIProvider provider) {
|
||||||
|
Set<UIProvider> existing = providers.get(provider.getNamespace());
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
existing = Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<UIProvider> updated = new HashSet<>(existing);
|
||||||
|
updated.add(provider);
|
||||||
|
providers.put(provider.getNamespace(), Set.copyOf(updated));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deregisterProvider(UIProvider provider) {
|
||||||
|
Set<UIProvider> existing = providers.get(provider.getNamespace());
|
||||||
|
|
||||||
|
if (existing != null && !existing.isEmpty()) {
|
||||||
|
Set<UIProvider> updated = new HashSet<>(existing);
|
||||||
|
updated.remove(provider);
|
||||||
|
providers.put(provider.getNamespace(), Set.copyOf(updated));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,13 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.ui.internal.components;
|
package org.openhab.core.ui.internal.components;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.common.registry.AbstractRegistry;
|
import org.openhab.core.common.registry.AbstractRegistry;
|
||||||
import org.openhab.core.storage.StorageService;
|
import org.openhab.core.common.registry.ManagedProvider;
|
||||||
|
import org.openhab.core.common.registry.Provider;
|
||||||
import org.openhab.core.ui.components.RootUIComponent;
|
import org.openhab.core.ui.components.RootUIComponent;
|
||||||
import org.openhab.core.ui.components.UIComponentRegistry;
|
import org.openhab.core.ui.components.UIComponentRegistry;
|
||||||
|
|
||||||
|
@ -23,26 +27,37 @@ import org.openhab.core.ui.components.UIComponentRegistry;
|
||||||
* It is instantiated by the {@link UIComponentRegistryFactoryImpl}.
|
* It is instantiated by the {@link UIComponentRegistryFactoryImpl}.
|
||||||
*
|
*
|
||||||
* @author Yannick Schaus - Initial contribution
|
* @author Yannick Schaus - Initial contribution
|
||||||
|
* @author Łukasz Dywicki - Support for dynamic registration of providers
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class UIComponentRegistryImpl extends AbstractRegistry<RootUIComponent, String, UIComponentProvider>
|
public class UIComponentRegistryImpl extends AbstractRegistry<RootUIComponent, String, UIComponentProvider>
|
||||||
implements UIComponentRegistry {
|
implements UIComponentRegistry {
|
||||||
|
|
||||||
String namespace;
|
|
||||||
StorageService storageService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a UI component registry for the specified namespace.
|
* Constructs a UI component registry for the specified namespace.
|
||||||
*
|
*
|
||||||
* @param namespace UI components namespace of this registry
|
* @param namespace UI components namespace of this registry
|
||||||
* @param storageService supporting storage service
|
|
||||||
*/
|
*/
|
||||||
public UIComponentRegistryImpl(String namespace, StorageService storageService) {
|
public UIComponentRegistryImpl(String namespace, @Nullable ManagedProvider<RootUIComponent, String> managedProvider,
|
||||||
|
@Nullable Set<UIProvider> providers) {
|
||||||
super(null);
|
super(null);
|
||||||
this.namespace = namespace;
|
if (managedProvider != null) {
|
||||||
this.storageService = storageService;
|
setManagedProvider(managedProvider);
|
||||||
UIComponentProvider provider = new UIComponentProvider(namespace, storageService);
|
}
|
||||||
|
if (providers != null && !providers.isEmpty()) {
|
||||||
|
for (Provider<RootUIComponent> provider : providers) {
|
||||||
addProvider(provider);
|
addProvider(provider);
|
||||||
setManagedProvider(provider);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addProvider(Provider<RootUIComponent> provider) {
|
||||||
|
super.addProvider(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeProvider(Provider<RootUIComponent> provider) {
|
||||||
|
super.removeProvider(provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.core.ui.internal.components;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.common.registry.Provider;
|
||||||
|
import org.openhab.core.ui.components.RootUIComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides components (pages, widgets, etc.) at runtime.
|
||||||
|
*
|
||||||
|
* @author Łukasz Dywicki - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public interface UIProvider extends Provider<RootUIComponent> {
|
||||||
|
String getNamespace();
|
||||||
|
}
|
Loading…
Reference in New Issue