Add null annotations to providers and ThingManager (#1412)

* Add null annotations to providers and ThingManager

Signed-off-by: Wouter Born <github@maindrain.net>
pull/1421/head
Wouter Born 2020-04-11 08:29:12 +02:00 committed by GitHub
parent 017532e2d4
commit fb7a7ac421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 561 additions and 585 deletions

View File

@ -17,6 +17,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.RuleProvider;
import org.openhab.core.common.registry.ProviderChangeListener;
@ -28,6 +29,7 @@ import org.osgi.service.component.annotations.Component;
*
* @author Simon Merschjohann - Initial contribution
*/
@NonNullByDefault
@Component(immediate = true, service = { ScriptedRuleProvider.class, RuleProvider.class })
public class ScriptedRuleProvider implements RuleProvider {
private final Collection<ProviderChangeListener<Rule>> listeners = new ArrayList<>();

View File

@ -23,6 +23,8 @@ import java.util.stream.Stream;
import javax.script.ScriptEngine;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Visibility;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler;
@ -51,6 +53,7 @@ import org.slf4j.LoggerFactory;
*
* @author Scott Rushworth - Initial contribution
*/
@NonNullByDefault
@Component
public class ScriptModuleTypeProvider implements ModuleTypeProvider {
@ -59,7 +62,7 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
@SuppressWarnings("unchecked")
@Override
public ModuleType getModuleType(String UID, Locale locale) {
public @Nullable ModuleType getModuleType(String UID, @Nullable Locale locale) {
if (ScriptActionHandler.TYPE_ID.equals(UID)) {
return getScriptActionType(locale);
} else if (ScriptConditionHandler.TYPE_ID.equals(UID)) {
@ -69,7 +72,7 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
}
}
private ModuleType getScriptActionType(Locale locale) {
private @Nullable ModuleType getScriptActionType(@Nullable Locale locale) {
if (parameterOptions.isEmpty()) {
return null;
} else {
@ -82,7 +85,7 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
}
}
private ModuleType getScriptConditionType(Locale locale) {
private @Nullable ModuleType getScriptConditionType(@Nullable Locale locale) {
if (parameterOptions.isEmpty()) {
return null;
} else {
@ -98,7 +101,7 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
*
* @return a list of {#link ConfigurationDescriptionParameter}s
*/
private List<ConfigDescriptionParameter> getConfigDescriptions(Locale locale) {
private List<ConfigDescriptionParameter> getConfigDescriptions(@Nullable Locale locale) {
List<ParameterOption> parameterOptionsList = new ArrayList<>();
for (Map.Entry<String, String> entry : parameterOptions.entrySet()) {
parameterOptionsList.add(new ParameterOption(entry.getKey(), entry.getValue()));
@ -114,8 +117,9 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
}
@Override
public Collection<ModuleType> getModuleTypes(Locale locale) {
return Stream.of(getScriptActionType(locale), getScriptConditionType(locale)).collect(Collectors.toList());
public Collection<ModuleType> getModuleTypes(@Nullable Locale locale) {
return (Collection<ModuleType>) Stream.of(getScriptActionType(locale), getScriptConditionType(locale))
.collect(Collectors.toList());
}
@Override

View File

@ -12,6 +12,8 @@
*/
package org.openhab.core.automation;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.dto.RuleDTO;
import org.openhab.core.automation.dto.RuleDTOMapper;
import org.openhab.core.common.registry.AbstractManagedProvider;
@ -28,6 +30,7 @@ import org.osgi.service.component.annotations.Reference;
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
* @author Markus Rathgeb - fix mapping between element and persistable element
*/
@NonNullByDefault
@Component(service = { RuleProvider.class, ManagedRuleProvider.class })
public class ManagedRuleProvider extends AbstractManagedProvider<Rule, String, RuleDTO> implements RuleProvider {
@ -47,7 +50,7 @@ public class ManagedRuleProvider extends AbstractManagedProvider<Rule, String, R
}
@Override
protected Rule toElement(String key, RuleDTO persistableElement) {
protected @Nullable Rule toElement(String key, RuleDTO persistableElement) {
return RuleDTOMapper.map(persistableElement);
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.parser.Parser;
@ -49,7 +50,7 @@ import org.slf4j.LoggerFactory;
*/
@SuppressWarnings("rawtypes")
@NonNullByDefault
public abstract class AbstractCommandProvider<E> implements ServiceTrackerCustomizer {
public abstract class AbstractCommandProvider<@NonNull E> implements ServiceTrackerCustomizer {
protected final Logger logger = LoggerFactory.getLogger(AbstractCommandProvider.class);

View File

@ -20,6 +20,8 @@ import java.net.URL;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.RuleRegistry;
import org.openhab.core.automation.parser.Parser;
@ -42,6 +44,7 @@ import org.osgi.framework.ServiceReference;
* @author Ana Dimova - Initial contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*/
@NonNullByDefault
public class CommandlineRuleImporter extends AbstractCommandProvider<Rule> {
private final RuleRegistry ruleRegistry;
@ -66,8 +69,8 @@ public class CommandlineRuleImporter extends AbstractCommandProvider<Rule> {
* @see AbstractCommandProvider#addingService(org.osgi.framework.ServiceReference)
*/
@Override
public Object addingService(@SuppressWarnings("rawtypes") ServiceReference reference) {
if (reference.getProperty(Parser.PARSER_TYPE).equals(Parser.PARSER_RULE)) {
public @Nullable Object addingService(@SuppressWarnings("rawtypes") @Nullable ServiceReference reference) {
if (reference != null && Parser.PARSER_RULE.equals(reference.getProperty(Parser.PARSER_TYPE))) {
return super.addingService(reference);
}
return null;

View File

@ -32,6 +32,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Rule;
@ -69,7 +70,7 @@ import org.slf4j.LoggerFactory;
*/
@SuppressWarnings("rawtypes")
@NonNullByDefault
public abstract class AbstractResourceBundleProvider<E> {
public abstract class AbstractResourceBundleProvider<@NonNull E> {
public AbstractResourceBundleProvider(String path) {
this.path = path;
@ -459,7 +460,7 @@ public abstract class AbstractResourceBundleProvider<E> {
}
}
protected void updateWaitingProviders(Parser<E> parser, Bundle bundle, URL url) {
protected void updateWaitingProviders(@Nullable Parser<E> parser, Bundle bundle, URL url) {
List<URL> urlList = waitingProviders.get(bundle);
if (parser == null) {
if (urlList == null) {

View File

@ -17,6 +17,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.template.TemplateProvider;
import org.openhab.core.automation.type.ModuleTypeProvider;
@ -33,7 +34,7 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
* @param <E>
*/
public class AutomationResourceBundlesEventQueue<E> implements Runnable {
public class AutomationResourceBundlesEventQueue<@NonNull E> implements Runnable {
/**
* This field keeps instance of {@link Logger} that is used for logging.

View File

@ -20,6 +20,8 @@ import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.ManagedRuleProvider;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.parser.Parser;
@ -40,12 +42,13 @@ import org.osgi.framework.Bundle;
* @author Ana Dimova - Initial contribution
* @author Kai Kreuzer - refactored (managed) provider and registry implementation
*/
@NonNullByDefault
public class RuleResourceBundleImporter extends AbstractResourceBundleProvider<Rule> {
/**
* This field holds the reference to the Rule Registry.
*/
protected ManagedRuleProvider mProvider;
protected @Nullable ManagedRuleProvider mProvider;
/**
* This constructor is responsible for initializing the path to resources and tracking the managing service of the

View File

@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.automation.parser.Parser;
import org.openhab.core.automation.parser.ParsingException;
@ -49,7 +50,7 @@ import org.slf4j.LoggerFactory;
* @author Ana Dimova - Initial contribution
*/
@NonNullByDefault
public abstract class AbstractFileProvider<E> implements Provider<E> {
public abstract class AbstractFileProvider<@NonNull E> implements Provider<E> {
protected static final String CONFIG_PROPERTY_ROOTS = "roots";
protected final Logger logger = LoggerFactory.getLogger(AbstractFileProvider.class);

View File

@ -26,9 +26,10 @@ import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.common.registry.AbstractProvider;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.items.ActiveItem;
import org.openhab.core.items.GenericItem;
import org.openhab.core.items.GroupFunction;
@ -38,9 +39,6 @@ import org.openhab.core.items.ItemFactory;
import org.openhab.core.items.ItemProvider;
import org.openhab.core.items.dto.GroupFunctionDTO;
import org.openhab.core.items.dto.ItemDTOMapper;
import org.openhab.core.types.StateDescriptionFragment;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.openhab.core.types.StateDescriptionFragmentProvider;
import org.openhab.core.model.core.EventType;
import org.openhab.core.model.core.ModelRepository;
import org.openhab.core.model.core.ModelRepositoryChangeListener;
@ -52,6 +50,9 @@ import org.openhab.core.model.items.ModelGroupFunction;
import org.openhab.core.model.items.ModelGroupItem;
import org.openhab.core.model.items.ModelItem;
import org.openhab.core.model.items.ModelNormalItem;
import org.openhab.core.types.StateDescriptionFragment;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.openhab.core.types.StateDescriptionFragmentProvider;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -68,6 +69,7 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Initial contribution
* @author Thomas Eichstaedt-Engelen - Initial contribution
*/
@NonNullByDefault
@Component(service = { ItemProvider.class, StateDescriptionFragmentProvider.class }, immediate = true)
public class GenericItemProvider extends AbstractProvider<Item>
implements ModelRepositoryChangeListener, ItemProvider, StateDescriptionFragmentProvider {
@ -218,7 +220,7 @@ public class GenericItemProvider extends AbstractProvider<Item>
}
}
private Item createItemFromModelItem(ModelItem modelItem) {
private @Nullable Item createItemFromModelItem(ModelItem modelItem) {
Item item = null;
if (modelItem instanceof ModelGroupItem) {
ModelGroupItem modelGroupItem = (ModelGroupItem) modelItem;
@ -264,7 +266,7 @@ public class GenericItemProvider extends AbstractProvider<Item>
}
}
private String extractFormat(String label) {
private @Nullable String extractFormat(@Nullable String label) {
if (label == null) {
return null;
}
@ -292,7 +294,7 @@ public class GenericItemProvider extends AbstractProvider<Item>
return new GroupItem(modelGroupItem.getName(), baseItem, groupFunction);
}
private void dispatchBindingsPerItemType(BindingConfigReader reader, String[] itemTypes) {
private void dispatchBindingsPerItemType(@Nullable BindingConfigReader reader, String[] itemTypes) {
for (String modelName : modelRepository.getAllModelNamesOfType("items")) {
ItemModel model = (ItemModel) modelRepository.getModel(modelName);
if (model != null) {
@ -338,7 +340,7 @@ public class GenericItemProvider extends AbstractProvider<Item>
internalDispatchBindings(null, modelName, item, bindings);
}
private void internalDispatchBindings(BindingConfigReader reader, String modelName, Item item,
private void internalDispatchBindings(@Nullable BindingConfigReader reader, String modelName, Item item,
EList<ModelBinding> bindings) {
for (ModelBinding binding : bindings) {
String bindingType = binding.getType();
@ -492,7 +494,7 @@ public class GenericItemProvider extends AbstractProvider<Item>
*
* @return An Item instance of type {@code itemType} or null if no item factory for it was found.
*/
private Item createItemOfType(String itemType, String itemName) {
private @Nullable Item createItemOfType(@Nullable String itemType, String itemName) {
if (itemType == null) {
return null;
}

View File

@ -28,6 +28,24 @@
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerId>eclipse</compilerId>
<compilerArgs>
<!-- Xtend doesn't support type annotations so warn on null analysis issues -->
<!-- See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=506374 -->
<arg>-warn:+nullAnnot(org.eclipse.jdt.annotation.Nullable|org.eclipse.jdt.annotation.NonNull|org.eclipse.jdt.annotation.NonNullByDefault),+inheritNullAnnot,-nullUncheckedConversion,+null,+inheritNullAnnot,+nullAnnotConflict,-nullUncheckedConversion,+nullAnnotRedundant,+nullDereference</arg>
</compilerArgs>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>

View File

@ -20,13 +20,15 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.openhab.core.config.core.Configuration;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.registry.AbstractProvider;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.model.item.BindingConfigParseException;
import org.openhab.core.model.item.BindingConfigReader;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.link.ItemChannelLink;
import org.openhab.core.thing.link.ItemChannelLinkProvider;
import org.openhab.core.model.item.BindingConfigParseException;
import org.openhab.core.model.item.BindingConfigReader;
import org.osgi.service.component.annotations.Component;
/**
@ -35,6 +37,7 @@ import org.osgi.service.component.annotations.Component;
* @author Oliver Libutzki - Initial contribution
* @author Alex Tugarev - Added parsing of multiple Channel UIDs
*/
@NonNullByDefault
@Component(immediate = true, service = { ItemChannelLinkProvider.class, BindingConfigReader.class })
public class GenericItemChannelLinkProvider extends AbstractProvider<ItemChannelLink>
implements BindingConfigReader, ItemChannelLinkProvider {
@ -48,7 +51,7 @@ public class GenericItemChannelLinkProvider extends AbstractProvider<ItemChannel
*/
protected Map<String, Set<String>> contextMap = new ConcurrentHashMap<>();
private Set<String> previousItemNames;
private @Nullable Set<String> previousItemNames;
@Override
public String getBindingType() {

View File

@ -12,6 +12,7 @@
*/
package org.openhab.core.thing;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.common.registry.DefaultAbstractManagedProvider;
import org.openhab.core.storage.StorageService;
import org.osgi.service.component.annotations.Activate;
@ -28,6 +29,7 @@ import org.osgi.service.component.annotations.Reference;
* @author Dennis Nobel - Integrated Storage
* @author Michael Grammling - Added dynamic configuration update
*/
@NonNullByDefault
@Component(immediate = true, service = { ThingProvider.class, ManagedThingProvider.class })
public class ManagedThingProvider extends DefaultAbstractManagedProvider<Thing, ThingUID> implements ThingProvider {

View File

@ -12,11 +12,14 @@
*/
package org.openhab.core.thing;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* {@link ThingManager} interface defines methods for managing a {@link Thing}.
*
* @author Yordan Zhelev - Initial contribution
*/
@NonNullByDefault
public interface ThingManager {
/**

View File

@ -34,6 +34,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.SafeCaller;
import org.openhab.core.common.ThreadPoolManager;
@ -120,6 +121,7 @@ import org.slf4j.LoggerFactory;
* @author Christoph Weitkamp - Added preconfigured ChannelGroupBuilder
* @author Yordan Zhelev - Added thing disabling mechanism
*/
@NonNullByDefault
@Component(immediate = true, service = { ThingTypeMigrationService.class, ThingManager.class })
public class ThingManagerImpl
implements ThingManager, ThingTracker, ThingTypeMigrationService, ReadyService.ReadyTracker {
@ -135,31 +137,30 @@ public class ThingManagerImpl
private final ScheduledExecutorService scheduler = ThreadPoolManager
.getScheduledPool(THING_MANAGER_THREADPOOL_NAME);
private EventPublisher eventPublisher;
private CommunicationManager communicationManager;
private ReadyService readyService;
private final List<ThingHandlerFactory> thingHandlerFactories = new CopyOnWriteArrayList<>();
private final Map<ThingUID, ThingHandler> thingHandlers = new ConcurrentHashMap<>();
private final Map<ThingHandlerFactory, Set<ThingHandler>> thingHandlersByFactory = new HashMap<>();
private ThingTypeRegistry thingTypeRegistry;
private ChannelTypeRegistry channelTypeRegistry;
private ChannelGroupTypeRegistry channelGroupTypeRegistry;
private ItemChannelLinkRegistry itemChannelLinkRegistry;
private ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
private final Set<Thing> things = new CopyOnWriteArraySet<>();
private final Map<ThingUID, Lock> thingLocks = new HashMap<>();
private final Set<ThingUID> thingUpdatedLock = new HashSet<>();
private final Set<String> loadedXmlThingTypes = new CopyOnWriteArraySet<>();
private SafeCaller safeCaller;
private volatile boolean active = false;
private StorageService storageService;
private Storage<String> storage;
private BundleResolver bundleResolver;
private final ChannelGroupTypeRegistry channelGroupTypeRegistry;
private final ChannelTypeRegistry channelTypeRegistry;
private final CommunicationManager communicationManager;
private final ConfigDescriptionRegistry configDescriptionRegistry;
private final ConfigDescriptionValidator configDescriptionValidator;
private final EventPublisher eventPublisher;
private final ThingTypeRegistry thingTypeRegistry;
private final ItemChannelLinkRegistry itemChannelLinkRegistry;
private final ReadyService readyService;
private final SafeCaller safeCaller;
private final Storage<String> storage;
private final ThingRegistryImpl thingRegistry;
private final ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
private final ThingHandlerCallback thingHandlerCallback = new ThingHandlerCallback() {
@ -246,9 +247,9 @@ public class ThingManagerImpl
@Override
public void thingUpdated(final Thing thing) {
thingUpdatedLock.add(thing.getUID());
AccessController.doPrivileged(new PrivilegedAction<Void>() {
AccessController.doPrivileged(new PrivilegedAction<@Nullable Void>() {
@Override
public Void run() {
public @Nullable Void run() {
Provider<Thing> provider = thingRegistry.getProvider(thing);
if (provider == null) {
throw new IllegalArgumentException(MessageFormat.format(
@ -347,20 +348,53 @@ public class ThingManagerImpl
}
};
private ThingRegistryImpl thingRegistry;
@Activate
public ThingManagerImpl( //
final @Reference BundleResolver bundleResolver,
final @Reference ChannelGroupTypeRegistry channelGroupTypeRegistry,
final @Reference ChannelTypeRegistry channelTypeRegistry,
final @Reference CommunicationManager communicationManager,
final @Reference ConfigDescriptionRegistry configDescriptionRegistry,
final @Reference ConfigDescriptionValidator configDescriptionValidator,
final @Reference EventPublisher eventPublisher,
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
final @Reference ReadyService readyService, //
final @Reference SafeCaller safeCaller, //
final @Reference StorageService storageService, //
final @Reference ThingRegistry thingRegistry,
final @Reference ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService,
final @Reference ThingTypeRegistry thingTypeRegistry) {
this.bundleResolver = bundleResolver;
this.channelGroupTypeRegistry = channelGroupTypeRegistry;
this.channelTypeRegistry = channelTypeRegistry;
this.communicationManager = communicationManager;
this.configDescriptionRegistry = configDescriptionRegistry;
this.configDescriptionValidator = configDescriptionValidator;
this.eventPublisher = eventPublisher;
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
this.readyService = readyService;
this.safeCaller = safeCaller;
this.thingRegistry = (ThingRegistryImpl) thingRegistry;
this.thingStatusInfoI18nLocalizationService = thingStatusInfoI18nLocalizationService;
this.thingTypeRegistry = thingTypeRegistry;
private BundleResolver bundleResolver;
readyService.registerTracker(this, new ReadyMarkerFilter().withType(XML_THING_TYPE));
this.thingRegistry.addThingTracker(this);
storage = storageService.getStorage(THING_STATUS_STORAGE_NAME, this.getClass().getClassLoader());
}
private ConfigDescriptionRegistry configDescriptionRegistry;
private ConfigDescriptionValidator configDescriptionValidator;
private final Set<Thing> things = new CopyOnWriteArraySet<>();
private final Set<ThingUID> thingUpdatedLock = new HashSet<>();
@Deactivate
protected synchronized void deactivate(ComponentContext componentContext) {
thingRegistry.removeThingTracker(this);
for (ThingHandlerFactory factory : thingHandlerFactories) {
removeThingHandlerFactory(factory);
}
readyService.unregisterTracker(this);
}
@Override
public void migrateThingType(final Thing thing, final ThingTypeUID thingTypeUID,
final Configuration configuration) {
final @Nullable Configuration configuration) {
final ThingType thingType = thingTypeRegistry.getThingType(thingTypeUID);
if (thingType == null) {
throw new IllegalStateException(
@ -379,8 +413,12 @@ public class ThingManagerImpl
final ThingHandlerFactory oldThingHandlerFactory = findThingHandlerFactory(thing.getThingTypeUID());
if (oldThingHandlerFactory != null) {
ThingHandler thingHandler = thing.getHandler();
unregisterAndDisposeHandler(oldThingHandlerFactory, thing, thingHandler);
waitUntilHandlerUnregistered(thing, 60 * 1000);
if (thingHandler != null) {
unregisterAndDisposeHandler(oldThingHandlerFactory, thing, thingHandler);
waitUntilHandlerUnregistered(thing, 60 * 1000);
} else {
logger.debug("No ThingHandler to dispose for {}", thing.getUID());
}
} else {
logger.debug("No ThingHandlerFactory available that can handle {}", thing.getThingTypeUID());
}
@ -511,7 +549,12 @@ public class ThingManagerImpl
logger.debug("Replacing uninitialized handler for updated thing '{}'",
thing.getThingTypeUID());
ThingHandlerFactory thingHandlerFactory = getThingHandlerFactory(thing);
unregisterHandler(thingHandler.getThing(), thingHandlerFactory);
if (thingHandlerFactory != null) {
unregisterHandler(thingHandler.getThing(), thingHandlerFactory);
} else {
logger.debug("No ThingHandlerFactory available that can handle {}",
thing.getThingTypeUID());
}
registerAndInitializeHandler(thing, thingHandlerFactory);
}
}
@ -524,16 +567,18 @@ public class ThingManagerImpl
}
}
private ThingHandler replaceThing(Thing oldThing, Thing newThing) {
private @Nullable ThingHandler replaceThing(@Nullable Thing oldThing, Thing newThing) {
final ThingHandler thingHandler = thingHandlers.get(newThing.getUID());
if (oldThing != newThing) {
this.things.remove(oldThing);
if (oldThing != null) {
this.things.remove(oldThing);
}
this.things.add(newThing);
}
return thingHandler;
}
private Thing getThing(ThingUID id) {
private @Nullable Thing getThing(ThingUID id) {
for (Thing thing : this.things) {
if (thing.getUID().equals(id)) {
return thing;
@ -546,7 +591,7 @@ public class ThingManagerImpl
return thingTypeRegistry.getThingType(thing.getThingTypeUID());
}
private ThingHandlerFactory findThingHandlerFactory(ThingTypeUID thingTypeUID) {
private @Nullable ThingHandlerFactory findThingHandlerFactory(ThingTypeUID thingTypeUID) {
for (ThingHandlerFactory factory : thingHandlerFactories) {
if (factory.supportsThingType(thingTypeUID)) {
return factory;
@ -645,11 +690,9 @@ public class ThingManagerImpl
ThingHandler handler = thing.getHandler();
if (handler == null) {
throw new IllegalStateException("Handler should not be null here");
} else {
if (handler.getThing() != thing) {
logger.warn("The model of {} is inconsistent [thing.getHandler().getThing() != thing]",
thing.getUID());
}
}
if (handler.getThing() != thing) {
logger.warn("The model of {} is inconsistent [thing.getHandler().getThing() != thing]", thing.getUID());
}
ThingType thingType = getThingType(thing);
if (thingType != null) {
@ -659,7 +702,7 @@ public class ThingManagerImpl
if (isInitializable(thing, thingType)) {
setThingStatus(thing, buildStatusInfo(ThingStatus.INITIALIZING, ThingStatusDetail.NONE));
doInitializeHandler(thing.getHandler());
doInitializeHandler(handler);
} else {
logger.debug("Thing '{}' not initializable, check required configuration parameters.", thing.getUID());
setThingStatus(thing,
@ -670,7 +713,7 @@ public class ThingManagerImpl
}
}
private boolean isInitializable(Thing thing, ThingType thingType) {
private boolean isInitializable(Thing thing, @Nullable ThingType thingType) {
if (!isComplete(thingType, thing.getUID(), tt -> tt.getConfigDescriptionURI(), thing.getConfiguration())) {
return false;
}
@ -696,8 +739,8 @@ public class ThingManagerImpl
* @param configuration the current configuration
* @return true if all required configuration parameters are given, false otherwise
*/
private <T extends Identifiable<?>> boolean isComplete(T prototype, UID targetUID,
Function<T, URI> configDescriptionURIFunction, Configuration configuration) {
private <T extends Identifiable<?>> boolean isComplete(@Nullable T prototype, UID targetUID,
Function<T, @Nullable URI> configDescriptionURIFunction, Configuration configuration) {
if (prototype == null) {
logger.debug("Prototype for '{}' is not known, assuming it is initializable", targetUID);
return true;
@ -718,12 +761,8 @@ public class ThingManagerImpl
return propertyKeys.containsAll(requiredParameters);
}
private ConfigDescription resolve(URI configDescriptionURI, Locale locale) {
if (configDescriptionURI == null) {
return null;
}
return configDescriptionRegistry != null
private @Nullable ConfigDescription resolve(@Nullable URI configDescriptionURI, @Nullable Locale locale) {
return configDescriptionURI != null
? configDescriptionRegistry.getConfigDescription(configDescriptionURI, locale)
: null;
}
@ -770,9 +809,12 @@ public class ThingManagerImpl
return thing.getBridgeUID() != null;
}
private Bridge getBridge(ThingUID bridgeUID) {
private @Nullable Bridge getBridge(@Nullable ThingUID bridgeUID) {
if (bridgeUID == null) {
return null;
}
Thing bridge = thingRegistry.get(bridgeUID);
return isBridge(bridge) ? (Bridge) bridge : null;
return bridge instanceof Bridge ? (Bridge) bridge : null;
}
private void unregisterHandler(Thing thing, ThingHandlerFactory thingHandlerFactory) {
@ -969,9 +1011,9 @@ public class ThingManagerImpl
@Override
public void run() {
try {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
AccessController.doPrivileged(new PrivilegedAction<@Nullable Void>() {
@Override
public Void run() {
public @Nullable Void run() {
thingRegistry.forceRemove(thing.getUID());
return null;
}
@ -988,32 +1030,11 @@ public class ThingManagerImpl
});
}
@Activate
protected synchronized void activate(ComponentContext componentContext) {
readyService.registerTracker(this, new ReadyMarkerFilter().withType(XML_THING_TYPE));
for (ThingHandlerFactory factory : thingHandlerFactories) {
handleThingHandlerFactoryAddition(getBundleIdentifier(factory));
}
thingRegistry.addThingTracker(this);
active = true;
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected synchronized void addThingHandlerFactory(ThingHandlerFactory thingHandlerFactory) {
logger.debug("Thing handler factory '{}' added", thingHandlerFactory.getClass().getSimpleName());
thingHandlerFactories.add(thingHandlerFactory);
if (active) {
handleThingHandlerFactoryAddition(getBundleIdentifier(thingHandlerFactory));
}
}
@Reference
public void setReadyService(ReadyService readyService) {
this.readyService = readyService;
}
public void unsetReadyService(ReadyService readyService) {
this.readyService = null;
handleThingHandlerFactoryAddition(getBundleIdentifier(thingHandlerFactory));
}
@Override
@ -1049,7 +1070,8 @@ public class ThingManagerImpl
return ReadyMarkerUtils.getIdentifier(bundleResolver.resolveBundle(thingHandlerFactory.getClass()));
}
private void registerAndInitializeHandler(final Thing thing, final ThingHandlerFactory thingHandlerFactory) {
private void registerAndInitializeHandler(final Thing thing,
final @Nullable ThingHandlerFactory thingHandlerFactory) {
if (thingHandlerFactory != null) {
final String identifier = getBundleIdentifier(thingHandlerFactory);
if (loadedXmlThingTypes.contains(identifier)) {
@ -1066,7 +1088,7 @@ public class ThingManagerImpl
}
}
private ThingHandlerFactory getThingHandlerFactory(Thing thing) {
private @Nullable ThingHandlerFactory getThingHandlerFactory(Thing thing) {
ThingHandlerFactory thingHandlerFactory = findThingHandlerFactory(thing.getThingTypeUID());
if (thingHandlerFactory != null) {
return thingHandlerFactory;
@ -1076,22 +1098,10 @@ public class ThingManagerImpl
return null;
}
@Deactivate
protected synchronized void deactivate(ComponentContext componentContext) {
active = false;
thingRegistry.removeThingTracker(this);
for (ThingHandlerFactory factory : thingHandlerFactories) {
removeThingHandlerFactory(factory);
}
readyService.unregisterTracker(this);
}
protected synchronized void removeThingHandlerFactory(ThingHandlerFactory thingHandlerFactory) {
logger.debug("Thing handler factory '{}' removed", thingHandlerFactory.getClass().getSimpleName());
thingHandlerFactories.remove(thingHandlerFactory);
if (active) {
handleThingHandlerFactoryRemoval(thingHandlerFactory);
}
handleThingHandlerFactoryRemoval(thingHandlerFactory);
}
private void handleThingHandlerFactoryRemoval(ThingHandlerFactory thingHandlerFactory) {
@ -1117,53 +1127,8 @@ public class ThingManagerImpl
return thingLocks.get(thingUID);
}
@Reference
protected void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Reference
protected void setThingRegistry(ThingRegistry thingRegistry) {
this.thingRegistry = (ThingRegistryImpl) thingRegistry;
}
protected void unsetEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = null;
}
protected void unsetThingRegistry(ThingRegistry thingRegistry) {
this.thingRegistry = null;
}
@Reference
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
this.configDescriptionRegistry = configDescriptionRegistry;
}
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
this.configDescriptionRegistry = null;
}
@Reference
protected void setConfigDescriptionValidator(ConfigDescriptionValidator configDescriptionValidator) {
this.configDescriptionValidator = configDescriptionValidator;
}
protected void unsetConfigDescriptionValidator(ConfigDescriptionValidator configDescriptionValidator) {
this.configDescriptionValidator = null;
}
@Reference
protected void setBundleResolver(BundleResolver bundleResolver) {
this.bundleResolver = bundleResolver;
}
protected void unsetBundleResolver(BundleResolver bundleResolver) {
this.bundleResolver = bundleResolver;
}
private ThingStatusInfo buildStatusInfo(ThingStatus thingStatus, ThingStatusDetail thingStatusDetail,
String description) {
@Nullable String description) {
ThingStatusInfoBuilder statusInfoBuilder = ThingStatusInfoBuilder.create(thingStatus, thingStatusDetail);
statusInfoBuilder.withDescription(description);
return statusInfoBuilder.build();
@ -1228,11 +1193,19 @@ public class ThingManagerImpl
logger.debug("Thing {} will be disabled.", thingUID);
boolean disposed = false;
if (isHandlerRegistered(thing)) {
// Dispose handler if registered.
ThingHandler thingHandler = thing.getHandler();
ThingHandlerFactory thingHandlerFactory = findThingHandlerFactory(thing.getThingTypeUID());
unregisterAndDisposeHandler(thingHandlerFactory, thing, thing.getHandler());
} else {
if (thingHandler != null && thingHandlerFactory != null) {
unregisterAndDisposeHandler(thingHandlerFactory, thing, thingHandler);
disposed = true;
}
}
if (!disposed) {
// Only set the correct status to the thing. There is no handler to be disposed
setThingStatus(thing, buildStatusInfo(ThingStatus.UNINITIALIZED, ThingStatusDetail.DISABLED));
}
@ -1254,12 +1227,6 @@ public class ThingManagerImpl
}
private void persistThingEnableStatus(ThingUID thingUID, boolean enabled) {
if (storage == null) {
logger.debug("Cannot persist enable status of thing with UID {}. Persistent storage unavailable.",
thingUID);
return;
}
logger.debug("Thing with UID {} will be persisted as {}.", thingUID, enabled ? "enabled." : "disabled.");
if (enabled) {
// Clear the disabled thing storage. Otherwise the handler will NOT be initialized later.
@ -1283,86 +1250,11 @@ public class ThingManagerImpl
}
private boolean isDisabledByStorage(ThingUID thingUID) {
return storage != null && storage.containsKey(thingUID.getAsString());
return storage.containsKey(thingUID.getAsString());
}
@Reference
protected void setThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
this.thingTypeRegistry = thingTypeRegistry;
void setBundleResolver(BundleResolver bundleResolver) {
this.bundleResolver = bundleResolver;
}
protected void unsetThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
this.thingTypeRegistry = null;
}
@Reference
protected void setChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
this.channelTypeRegistry = channelTypeRegistry;
}
protected void unsetChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
this.channelTypeRegistry = null;
}
@Reference
protected void setChannelGroupTypeRegistry(ChannelGroupTypeRegistry channelGroupTypeRegistry) {
this.channelGroupTypeRegistry = channelGroupTypeRegistry;
}
protected void unsetChannelGroupTypeRegistry(ChannelGroupTypeRegistry channelGroupTypeRegistry) {
this.channelGroupTypeRegistry = null;
}
@Reference
protected void setItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
}
protected void unsetItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
this.itemChannelLinkRegistry = null;
}
@Reference
protected void setThingStatusInfoI18nLocalizationService(
ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService) {
this.thingStatusInfoI18nLocalizationService = thingStatusInfoI18nLocalizationService;
}
protected void unsetThingStatusInfoI18nLocalizationService(
ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService) {
this.thingStatusInfoI18nLocalizationService = null;
}
@Reference
protected void setInboundCommunication(CommunicationManager communicationManager) {
this.communicationManager = communicationManager;
}
protected void unsetInboundCommunication(CommunicationManager communicationManager) {
this.communicationManager = null;
}
@Reference
protected void setSafeCaller(SafeCaller safeCaller) {
this.safeCaller = safeCaller;
}
protected void unsetSafeCaller(SafeCaller safeCaller) {
this.safeCaller = null;
}
@Reference
protected void setStorageService(StorageService storageService) {
if (this.storageService != storageService) {
this.storageService = storageService;
storage = storageService.getStorage(THING_STATUS_STORAGE_NAME, this.getClass().getClassLoader());
}
}
protected void unsetStorageService(StorageService storageService) {
if (this.storageService == storageService) {
this.storageService = null;
this.storage = null;
}
}
}

View File

@ -12,6 +12,7 @@
*/
package org.openhab.core.thing.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingRegistryChangeListener;
@ -25,6 +26,7 @@ import org.openhab.core.thing.ThingRegistryChangeListener;
* @author Michael Grammling - Added dynamic configuration update
* @author Simon Kaufmann - Added THING_REMOVING state
*/
@NonNullByDefault
public interface ThingTracker {
public enum ThingTrackerEvent {

View File

@ -14,6 +14,7 @@ package org.openhab.core.thing.link;
import java.util.Collection;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.common.registry.DefaultAbstractManagedProvider;
import org.openhab.core.storage.StorageService;
import org.openhab.core.thing.ThingUID;
@ -27,6 +28,7 @@ import org.osgi.service.component.annotations.Reference;
*
* @author Dennis Nobel - Initial contribution
*/
@NonNullByDefault
@Component(immediate = true, service = { ItemChannelLinkProvider.class, ManagedItemChannelLinkProvider.class })
public class ManagedItemChannelLinkProvider extends DefaultAbstractManagedProvider<ItemChannelLink, String>
implements ItemChannelLinkProvider {

View File

@ -24,6 +24,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@ -60,18 +61,12 @@ public class ChannelItemProviderTest {
private static final NumberItem ITEM = new NumberItem(ITEM_NAME);
private static final ItemChannelLink LINK = new ItemChannelLink(ITEM_NAME, CHANNEL_UID);
@Mock
private ItemRegistry itemRegistry;
@Mock
private ThingRegistry thingRegistry;
@Mock
private ItemFactory itemFactory;
@Mock
private ProviderChangeListener<Item> listener;
@Mock
private LocaleProvider localeProvider;
@Mock
private ItemChannelLinkRegistry linkRegistry;
private @Mock ItemFactory itemFactoryMock;
private @Mock ItemRegistry itemRegistryMock;
private @Mock ItemChannelLinkRegistry linkRegistryMock;
private @Mock ProviderChangeListener<@NonNull Item> listenerMock;
private @Mock LocaleProvider localeProviderMock;
private @Mock ThingRegistry thingRegistryMock;
private ChannelItemProvider provider;
@ -86,9 +81,9 @@ public class ChannelItemProviderTest {
props.put("initialDelay", "false");
provider.activate(props);
when(thingRegistry.getChannel(same(CHANNEL_UID))).thenReturn(CHANNEL);
when(itemFactory.createItem(CoreItemFactory.NUMBER, ITEM_NAME)).thenReturn(ITEM);
when(localeProvider.getLocale()).thenReturn(Locale.ENGLISH);
when(thingRegistryMock.getChannel(same(CHANNEL_UID))).thenReturn(CHANNEL);
when(itemFactoryMock.createItem(CoreItemFactory.NUMBER, ITEM_NAME)).thenReturn(ITEM);
when(localeProviderMock.getLocale()).thenReturn(Locale.ENGLISH);
}
@Test
@ -96,17 +91,17 @@ public class ChannelItemProviderTest {
resetAndPrepareListener();
provider.thingRegistryListener.added(THING);
verify(listener, only()).added(same(provider), same(ITEM));
verify(listenerMock, only()).added(same(provider), same(ITEM));
}
@Test
public void testItemCreationFromThingAlreadyExists() {
when(itemRegistry.get(eq(ITEM_NAME))).thenReturn(ITEM);
when(itemRegistryMock.get(eq(ITEM_NAME))).thenReturn(ITEM);
resetAndPrepareListener();
provider.thingRegistryListener.added(THING);
verify(listener, never()).added(same(provider), same(ITEM));
verify(listenerMock, never()).added(same(provider), same(ITEM));
}
@Test
@ -116,22 +111,22 @@ public class ChannelItemProviderTest {
resetAndPrepareListener();
provider.thingRegistryListener.removed(THING);
verify(listener, never()).added(same(provider), same(ITEM));
verify(listener, only()).removed(same(provider), same(ITEM));
verify(listenerMock, never()).added(same(provider), same(ITEM));
verify(listenerMock, only()).removed(same(provider), same(ITEM));
}
@Test
public void testItemCreationFromLinkNotThere() {
provider.linkRegistryListener.added(LINK);
verify(listener, only()).added(same(provider), same(ITEM));
verify(listenerMock, only()).added(same(provider), same(ITEM));
}
@Test
public void testItemCreationFromLinkAlreadyExists() {
when(itemRegistry.get(eq(ITEM_NAME))).thenReturn(ITEM);
when(itemRegistryMock.get(eq(ITEM_NAME))).thenReturn(ITEM);
provider.linkRegistryListener.added(LINK);
verify(listener, never()).added(same(provider), same(ITEM));
verify(listenerMock, never()).added(same(provider), same(ITEM));
}
@Test
@ -141,8 +136,8 @@ public class ChannelItemProviderTest {
resetAndPrepareListener();
provider.linkRegistryListener.removed(LINK);
verify(listener, never()).added(same(provider), same(ITEM));
verify(listener, only()).removed(same(provider), same(ITEM));
verify(listenerMock, never()).added(same(provider), same(ITEM));
verify(listenerMock, only()).removed(same(provider), same(ITEM));
}
@Test
@ -152,14 +147,14 @@ public class ChannelItemProviderTest {
resetAndPrepareListener();
provider.itemRegistryListener.beforeAdding(new NumberItem(ITEM_NAME));
verify(listener, only()).removed(same(provider), same(ITEM));
verify(listener, never()).added(same(provider), same(ITEM));
verify(listenerMock, only()).removed(same(provider), same(ITEM));
verify(listenerMock, never()).added(same(provider), same(ITEM));
}
@Test
public void testDisableBeforeDelayedInitialization() throws Exception {
provider = createProvider();
reset(linkRegistry);
reset(linkRegistryMock);
// Set the initialization delay to 40ms so we don't have to wait 2000ms to do the assertion
Field field = ChannelItemProvider.class.getDeclaredField("INITIALIZATION_DELAY_NANOS");
@ -174,8 +169,8 @@ public class ChannelItemProviderTest {
provider.activate(props);
provider.linkRegistryListener.added(LINK);
verify(listener, never()).added(same(provider), same(ITEM));
verify(linkRegistry, never()).getAll();
verify(listenerMock, never()).added(same(provider), same(ITEM));
verify(linkRegistryMock, never()).getAll();
props = new HashMap<>();
props.put("enabled", "false");
@ -184,32 +179,32 @@ public class ChannelItemProviderTest {
Thread.sleep(100);
provider.linkRegistryListener.added(LINK);
verify(listener, never()).added(same(provider), same(ITEM));
verify(linkRegistry, never()).getAll();
verify(listenerMock, never()).added(same(provider), same(ITEM));
verify(linkRegistryMock, never()).getAll();
}
@SuppressWarnings("unchecked")
private void resetAndPrepareListener() {
reset(listener);
reset(listenerMock);
doAnswer(invocation -> {
// this is crucial as it mimics the real ItemRegistry's behavior
provider.itemRegistryListener.afterRemoving((Item) invocation.getArguments()[1]);
return null;
}).when(listener).removed(same(provider), any(Item.class));
}).when(listenerMock).removed(same(provider), any(Item.class));
doAnswer(invocation -> {
// this is crucial as it mimics the real ItemRegistry's behavior
provider.itemRegistryListener.beforeAdding((Item) invocation.getArguments()[1]);
return null;
}).when(listener).added(same(provider), any(Item.class));
when(linkRegistry.getBoundChannels(eq(ITEM_NAME))).thenReturn(Collections.singleton(CHANNEL_UID));
when(linkRegistry.getLinks(eq(CHANNEL_UID))).thenReturn(Collections.singleton(LINK));
}).when(listenerMock).added(same(provider), any(Item.class));
when(linkRegistryMock.getBoundChannels(eq(ITEM_NAME))).thenReturn(Collections.singleton(CHANNEL_UID));
when(linkRegistryMock.getLinks(eq(CHANNEL_UID))).thenReturn(Collections.singleton(LINK));
}
private ChannelItemProvider createProvider() {
ChannelItemProvider provider = new ChannelItemProvider(localeProvider, mock(ChannelTypeRegistry.class),
thingRegistry, itemRegistry, linkRegistry);
provider.addItemFactory(itemFactory);
provider.addProviderChangeListener(listener);
ChannelItemProvider provider = new ChannelItemProvider(localeProviderMock, mock(ChannelTypeRegistry.class),
thingRegistryMock, itemRegistryMock, linkRegistryMock);
provider.addItemFactory(itemFactoryMock);
provider.addProviderChangeListener(listenerMock);
return provider;
}

View File

@ -17,103 +17,129 @@ import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.openhab.core.common.SafeCaller;
import org.openhab.core.config.core.ConfigDescriptionRegistry;
import org.openhab.core.config.core.validation.ConfigDescriptionValidator;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.service.ReadyService;
import org.openhab.core.storage.Storage;
import org.openhab.core.storage.StorageService;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.openhab.core.thing.i18n.ThingStatusInfoI18nLocalizationService;
import org.openhab.core.thing.internal.ThingTracker.ThingTrackerEvent;
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
import org.openhab.core.thing.type.ChannelGroupTypeRegistry;
import org.openhab.core.thing.type.ChannelTypeRegistry;
import org.openhab.core.thing.type.ThingTypeRegistry;
import org.openhab.core.util.BundleResolver;
import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentContext;
/**
* @author Simon Kaufmann - Initial contribution
*/
@NonNullByDefault
public class ThingManagerImplTest {
private @Mock BundleResolver mockBundleResolver;
private @Mock Bundle mockBundle;
private @Mock ComponentContext mockComponentContext;
private @Mock ReadyService mockReadyService;
private @Mock Thing mockThing;
private @Mock @NonNullByDefault({}) Bundle bundleMock;
private @Mock @NonNullByDefault({}) BundleResolver bundleResolverMock;
private @Mock @NonNullByDefault({}) ChannelGroupTypeRegistry channelGroupTypeRegistryMock;
private @Mock @NonNullByDefault({}) ChannelTypeRegistry channelTypeRegistryMock;
private @Mock @NonNullByDefault({}) CommunicationManager communicationManagerMock;
private @Mock @NonNullByDefault({}) EventPublisher eventPublisherMock;
private @Mock @NonNullByDefault({}) ConfigDescriptionRegistry configDescriptionRegistryMock;
private @Mock @NonNullByDefault({}) ConfigDescriptionValidator configDescriptionValidatorMock;
private @Mock @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistryMock;
private @Mock @NonNullByDefault({}) ThingTypeRegistry thingTypeRegistryMock;
private @Mock @NonNullByDefault({}) ReadyService readyServiceMock;
private @Mock @NonNullByDefault({}) SafeCaller safeCallerMock;
private @Mock @NonNullByDefault({}) Storage<Object> storageMock;
private @Mock @NonNullByDefault({}) StorageService storageServiceMock;
private @Mock @NonNullByDefault({}) Thing thingMock;
private @Mock @NonNullByDefault({}) ThingRegistryImpl thingRegistryMock;
private @Mock StorageService mockStorageService;
private @Mock Storage<Object> mockStorage;
private final ThingRegistryImpl thingRegistry = new ThingRegistryImpl();
// This class is final so it cannot be mocked
private final ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService = new ThingStatusInfoI18nLocalizationService();
@Before
public void setup() {
initMocks(this);
when(mockBundle.getSymbolicName()).thenReturn("test");
when(mockBundleResolver.resolveBundle(any())).thenReturn(mockBundle);
when(mockThing.getUID()).thenReturn(new ThingUID("test", "thing"));
when(bundleMock.getSymbolicName()).thenReturn("test");
when(bundleResolverMock.resolveBundle(any())).thenReturn(bundleMock);
when(thingMock.getUID()).thenReturn(new ThingUID("test", "thing"));
}
private ThingManagerImpl createThingManager() {
return new ThingManagerImpl(bundleResolverMock, channelGroupTypeRegistryMock, channelTypeRegistryMock,
communicationManagerMock, configDescriptionRegistryMock, configDescriptionValidatorMock,
eventPublisherMock, itemChannelLinkRegistryMock, readyServiceMock, safeCallerMock, storageServiceMock,
thingRegistryMock, thingStatusInfoI18nLocalizationService, thingTypeRegistryMock);
}
@Test
public void testThingHandlerFactoryLifecycle() {
public void thingHandlerFactoryLifecycle() {
ThingHandlerFactory mockFactory1 = mock(ThingHandlerFactory.class);
ThingHandlerFactory mockFactory2 = mock(ThingHandlerFactory.class);
ThingManagerImpl thingManager = new ThingManagerImpl();
thingManager.setBundleResolver(mockBundleResolver);
thingManager.setThingRegistry(thingRegistry);
thingManager.setReadyService(mockReadyService);
thingManager.thingAdded(mockThing, null);
ThingManagerImpl thingManager = createThingManager();
thingManager.thingAdded(thingMock, ThingTrackerEvent.THING_ADDED);
// ensure usage is delayed until activation
thingManager.addThingHandlerFactory(mockFactory1);
verify(mockFactory1, times(0)).supportsThingType(any());
thingManager.activate(mockComponentContext);
verify(mockFactory1, atLeastOnce()).supportsThingType(any());
thingManager.removeThingHandlerFactory(mockFactory1);
// ensure it is directly used
thingManager.addThingHandlerFactory(mockFactory2);
verify(mockFactory2, atLeastOnce()).supportsThingType(any());
thingManager.removeThingHandlerFactory(mockFactory2);
}
@Test
public void testCallSetEnabledWithUnknownThingUID() throws Exception {
public void setEnabledWithUnknownThingUID() throws Exception {
ThingUID unknownUID = new ThingUID("someBundle", "someType", "someID");
ThingManagerImpl thingManager = new ThingManagerImpl();
when(mockStorageService.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(mockStorage);
thingManager.setStorageService(mockStorageService);
when(storageServiceMock.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(storageMock);
ThingManagerImpl thingManager = createThingManager();
thingManager.setEnabled(unknownUID, true);
verify(mockStorage).remove(eq(unknownUID.getAsString()));
verify(storageMock).remove(eq(unknownUID.getAsString()));
thingManager.setEnabled(unknownUID, false);
verify(mockStorage).put(eq(unknownUID.getAsString()), eq(""));
verify(storageMock).put(eq(unknownUID.getAsString()), eq(""));
}
@Test
public void testCallIsEnabledWithUnknownThingUIDAndNullStorage() throws Exception {
public void isEnabledWithUnknownThingUIDAndNullStorage() throws Exception {
ThingUID unknownUID = new ThingUID("someBundle", "someType", "someID");
ThingManagerImpl thingManager = new ThingManagerImpl();
when(mockStorageService.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(mockStorage);
thingManager.setStorageService(mockStorageService);
when(storageServiceMock.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(storageMock);
ThingManagerImpl thingManager = createThingManager();
assertEquals(thingManager.isEnabled(unknownUID), true);
}
@Test
public void testCallIsEnabledWithUnknownThingUIDAndNonNullStorage() throws Exception {
public void isEnabledWithUnknownThingUIDAndNonNullStorage() throws Exception {
ThingUID unknownUID = new ThingUID("someBundle", "someType", "someID");
ThingManagerImpl thingManager = new ThingManagerImpl();
when(mockStorage.containsKey(unknownUID.getAsString())).thenReturn(false);
when(mockStorageService.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(mockStorage);
thingManager.setStorageService(mockStorageService);
when(storageMock.containsKey(unknownUID.getAsString())).thenReturn(false);
when(storageServiceMock.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(storageMock);
ThingManagerImpl thingManager = createThingManager();
assertEquals(thingManager.isEnabled(unknownUID), true);
when(mockStorage.containsKey(unknownUID.getAsString())).thenReturn(true);
when(mockStorageService.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(mockStorage);
thingManager.setStorageService(mockStorageService);
when(storageMock.containsKey(unknownUID.getAsString())).thenReturn(true);
when(storageServiceMock.getStorage(eq("thing_status_storage"), any(ClassLoader.class))).thenReturn(storageMock);
assertEquals(thingManager.isEnabled(unknownUID), false);
}
}

View File

@ -17,6 +17,8 @@ import java.util.Objects;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.storage.Storage;
import org.openhab.core.storage.StorageService;
import org.slf4j.Logger;
@ -41,8 +43,9 @@ import org.slf4j.LoggerFactory;
* @param <PE>
* type of the persistable element
*/
public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE> extends AbstractProvider<E>
implements ManagedProvider<E, K> {
@NonNullByDefault
public abstract class AbstractManagedProvider<@NonNull E extends Identifiable<K>, @NonNull K, PE>
extends AbstractProvider<E> implements ManagedProvider<E, K> {
private volatile Storage<PE> storage;
@ -67,37 +70,26 @@ public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE>
@Override
public Collection<E> getAll() {
return storage.getKeys().stream().map(key -> {
PE persistableElement = storage.get(key);
if (persistableElement != null) {
return toElement(key, persistableElement);
} else {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
return (Collection<E>) storage.getKeys().stream().map(this::getElement).filter(Objects::nonNull)
.collect(Collectors.toList());
}
@Override
public E get(K key) {
if (key == null) {
throw new IllegalArgumentException("Cannot get null element");
}
public @Nullable E get(K key) {
return getElement(keyToString(key));
}
String keyAsString = keyToString(key);
PE persistableElement = storage.get(keyAsString);
if (persistableElement != null) {
return toElement(keyAsString, persistableElement);
} else {
return null;
}
private @Nullable E getElement(String key) {
PE persistableElement = storage.get(key);
return persistableElement != null ? toElement(key, persistableElement) : null;
}
@Override
public E remove(K key) {
public @Nullable E remove(K key) {
String keyAsString = keyToString(key);
PE persistableElement = storage.remove(keyAsString);
if (persistableElement != null) {
@Nullable
E element = toElement(keyAsString, persistableElement);
if (element != null) {
notifyListenersAboutRemovedElement(element);
@ -110,12 +102,16 @@ public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE>
}
@Override
public E update(E element) {
public @Nullable E update(E element) {
String key = getKeyAsString(element);
if (storage.get(key) != null) {
PE persistableElement = storage.put(key, toPersistableElement(element));
if (persistableElement != null) {
@Nullable
E oldElement = toElement(key, persistableElement);
if (oldElement == null) {
oldElement = element;
}
notifyListenersAboutUpdatedElement(oldElement, element);
logger.debug("Updated element {} in {}.", key, this.getClass().getSimpleName());
return oldElement;
@ -128,7 +124,7 @@ public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE>
return null;
}
private @NonNull String getKeyAsString(@NonNull E element) {
private String getKeyAsString(E element) {
return keyToString(element.getUID());
}
@ -145,7 +141,7 @@ public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE>
* @param key key
* @return string representation of the key
*/
protected abstract @NonNull String keyToString(@NonNull K key);
protected abstract String keyToString(K key);
/**
* Converts the persistable element into the original element.
@ -154,7 +150,7 @@ public abstract class AbstractManagedProvider<E extends Identifiable<K>, K, PE>
* @param persistableElement persistable element
* @return original element
*/
protected abstract E toElement(@NonNull String key, @NonNull PE persistableElement);
protected abstract @Nullable E toElement(String key, @NonNull PE persistableElement);
/**
* Converts the original element into an element that can be persisted.

View File

@ -15,6 +15,9 @@ package org.openhab.core.common.registry;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -27,7 +30,8 @@ import org.slf4j.LoggerFactory;
* @param <E>
* type of the provided elements
*/
public abstract class AbstractProvider<E> implements Provider<E> {
@NonNullByDefault
public abstract class AbstractProvider<@NonNull E> implements Provider<E> {
private enum EventType {
ADDED,
@ -48,7 +52,7 @@ public abstract class AbstractProvider<E> implements Provider<E> {
listeners.remove(listener);
}
private void notifyListeners(E oldElement, E element, EventType eventType) {
private void notifyListeners(@Nullable E oldElement, E element, EventType eventType) {
for (ProviderChangeListener<E> listener : this.listeners) {
try {
switch (eventType) {
@ -59,7 +63,7 @@ public abstract class AbstractProvider<E> implements Provider<E> {
listener.removed(this, element);
break;
case UPDATED:
listener.updated(this, oldElement, element);
listener.updated(this, oldElement != null ? oldElement : element, element);
break;
default:
break;

View File

@ -52,7 +52,7 @@ import org.slf4j.LoggerFactory;
* @param <E> type of the element
*/
@NonNullByDefault
public abstract class AbstractRegistry<E extends Identifiable<K>, K, P extends Provider<E>>
public abstract class AbstractRegistry<@NonNull E extends Identifiable<K>, @NonNull K, @NonNull P extends Provider<E>>
implements ProviderChangeListener<E>, Registry<E, K> {
private enum EventType {

View File

@ -12,6 +12,9 @@
*/
package org.openhab.core.common.registry;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.storage.StorageService;
/**
@ -27,7 +30,8 @@ import org.openhab.core.storage.StorageService;
* @param <K>
* type of the element key
*/
public abstract class DefaultAbstractManagedProvider<E extends Identifiable<K>, K>
@NonNullByDefault
public abstract class DefaultAbstractManagedProvider<@NonNull E extends Identifiable<K>, @NonNull K>
extends AbstractManagedProvider<E, K, E> {
public DefaultAbstractManagedProvider(final StorageService storageService) {
@ -35,7 +39,7 @@ public abstract class DefaultAbstractManagedProvider<E extends Identifiable<K>,
}
@Override
protected E toElement(String key, E element) {
protected @Nullable E toElement(String key, E element) {
return element;
}

View File

@ -13,6 +13,7 @@
package org.openhab.core.common.registry;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
@ -26,14 +27,15 @@ import org.eclipse.jdt.annotation.Nullable;
* @param <K>
* type of the element key
*/
public interface ManagedProvider<E extends Identifiable<K>, K> extends Provider<E> {
@NonNullByDefault
public interface ManagedProvider<@NonNull E extends Identifiable<K>, @NonNull K> extends Provider<E> {
/**
* Adds an element.
*
* @param element element to be added
*/
void add(@NonNull E element);
void add(E element);
/**
* Removes an element and returns the removed element.
@ -43,7 +45,7 @@ public interface ManagedProvider<E extends Identifiable<K>, K> extends Provider<
* key exists
*/
@Nullable
E remove(@NonNull K key);
E remove(K key);
/**
* Updates an element.
@ -53,7 +55,7 @@ public interface ManagedProvider<E extends Identifiable<K>, K> extends Provider<
* exists
*/
@Nullable
E update(@NonNull E element);
E update(E element);
/**
* Returns an element for the given key or null if no element for the given

View File

@ -14,6 +14,7 @@ package org.openhab.core.common.registry;
import java.util.Collection;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
@ -27,7 +28,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
* @param <E> type of the provided elements
*/
@NonNullByDefault
public interface Provider<E> {
public interface Provider<@NonNull E> {
/**
* Adds a {@link ProviderChangeListener} which must be notified if there are

View File

@ -12,6 +12,7 @@
*/
package org.openhab.core.common.registry;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
@ -24,7 +25,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
* @param <E> type of the element from the provider
*/
@NonNullByDefault
public interface ProviderChangeListener<E> {
public interface ProviderChangeListener<@NonNull E> {
/**
* Notifies the listener that a single element has been added.

View File

@ -13,6 +13,7 @@
package org.openhab.core.internal.items;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.registry.AbstractManagedProvider;
import org.openhab.core.items.ManagedMetadataProvider;
import org.openhab.core.items.Metadata;
@ -33,8 +34,8 @@ import org.slf4j.LoggerFactory;
*
* @author Kai Kreuzer - Initial contribution
*/
@Component(immediate = true, service = { MetadataProvider.class, ManagedMetadataProvider.class })
@NonNullByDefault
@Component(immediate = true, service = { MetadataProvider.class, ManagedMetadataProvider.class })
public class ManagedMetadataProviderImpl extends AbstractManagedProvider<Metadata, MetadataKey, Metadata>
implements ManagedMetadataProvider {
@ -56,7 +57,7 @@ public class ManagedMetadataProviderImpl extends AbstractManagedProvider<Metadat
}
@Override
protected Metadata toElement(String key, Metadata persistableElement) {
protected @Nullable Metadata toElement(String key, Metadata persistableElement) {
return persistableElement;
}

View File

@ -12,6 +12,7 @@
*/
package org.openhab.core.items;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.common.registry.Provider;
@ -23,6 +24,6 @@ import org.openhab.core.common.registry.Provider;
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public interface ItemProvider extends Provider<Item> {
public interface ItemProvider extends Provider<@NonNull Item> {
}

View File

@ -54,10 +54,10 @@ import com.google.gson.InstanceCreator;
* @author Kai Kreuzer - improved return values
* @author Alex Tugarev - added tags
*/
@NonNullByDefault
@Component(immediate = true, service = { ItemProvider.class, ManagedItemProvider.class })
public class ManagedItemProvider extends AbstractManagedProvider<Item, String, PersistedItem> implements ItemProvider {
@NonNullByDefault
public static class PersistedItem {
public PersistedItem(String itemType) {
@ -78,7 +78,7 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
public static class PersistedItemInstanceCreator implements InstanceCreator<PersistedItem> {
@Override
public PersistedItem createInstance(Type type) {
public PersistedItem createInstance(@NonNullByDefault({}) Type type) {
return new PersistedItem("");
}
}
@ -100,7 +100,7 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
* @param recursive if set to true all members of the item will be removed, too.
* @return removed item or null if no item with that name exists
*/
public Item remove(String itemName, boolean recursive) {
public @Nullable Item remove(String itemName, boolean recursive) {
Item item = get(itemName);
if (recursive && item instanceof GroupItem) {
for (String member : getMemberNamesRecursively((GroupItem) item, getAll())) {
@ -128,7 +128,7 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
return memberNames;
}
private Item createItem(String itemType, String itemName) {
private @Nullable Item createItem(String itemType, String itemName) {
for (ItemFactory factory : itemFactories) {
Item item = factory.createItem(itemType, itemName);
if (item != null) {
@ -195,12 +195,13 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
}
@Override
protected Item toElement(String itemName, PersistedItem persistedItem) {
protected @Nullable Item toElement(String itemName, PersistedItem persistedItem) {
Item item = null;
if (persistedItem.itemType.equals(GroupItem.TYPE)) {
if (persistedItem.baseItemType != null) {
Item baseItem = createItem(persistedItem.baseItemType, itemName);
if (GroupItem.TYPE.equals(persistedItem.itemType)) {
String baseItemType = persistedItem.baseItemType;
if (baseItemType != null) {
Item baseItem = createItem(baseItemType, itemName);
if (persistedItem.functionName != null) {
GroupFunction function = getGroupFunction(persistedItem, baseItem);
item = new GroupItem(itemName, baseItem, function);
@ -227,7 +228,7 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
return item;
}
private GroupFunction getGroupFunction(PersistedItem persistedItem, Item baseItem) {
private GroupFunction getGroupFunction(PersistedItem persistedItem, @Nullable Item baseItem) {
GroupFunctionDTO functionDTO = new GroupFunctionDTO();
functionDTO.name = persistedItem.functionName;
if (persistedItem.functionParams != null) {
@ -237,24 +238,22 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
}
private void configureItem(PersistedItem persistedItem, ActiveItem item) {
if (item != null) {
List<String> groupNames = persistedItem.groupNames;
if (groupNames != null) {
for (String groupName : groupNames) {
item.addGroupName(groupName);
}
List<String> groupNames = persistedItem.groupNames;
if (groupNames != null) {
for (String groupName : groupNames) {
item.addGroupName(groupName);
}
Set<String> tags = persistedItem.tags;
if (tags != null) {
for (String tag : tags) {
item.addTag(tag);
}
}
item.setLabel(persistedItem.label);
item.setCategory(persistedItem.category);
}
Set<String> tags = persistedItem.tags;
if (tags != null) {
for (String tag : tags) {
item.addTag(tag);
}
}
item.setLabel(persistedItem.label);
item.setCategory(persistedItem.category);
}
@Override

View File

@ -26,6 +26,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -60,6 +62,7 @@ import org.slf4j.LoggerFactory;
* @author Benedikt Niehues - Initial contribution
* @author Markus Rathgeb - Migrated Groovy tests to pure Java ones and made it more robust
*/
@NonNullByDefault
public class RunRuleModuleTest extends JavaOSGiTest {
private final Logger logger = LoggerFactory.getLogger(RunRuleModuleTest.class);
@ -182,7 +185,7 @@ public class RunRuleModuleTest extends JavaOSGiTest {
}
@Override
public EventFilter getEventFilter() {
public @Nullable EventFilter getEventFilter() {
return null;
}
});

View File

@ -26,6 +26,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
@ -67,6 +69,7 @@ import org.slf4j.LoggerFactory;
* @author Benedikt Niehues - Initial contribution
* @author Markus Rathgeb - Migrated Groovy tests to pure Java ones and made it more robust
*/
@NonNullByDefault
public class RuntimeRuleTest extends JavaOSGiTest {
private final Logger logger = LoggerFactory.getLogger(RuntimeRuleTest.class);
@ -115,7 +118,7 @@ public class RuntimeRuleTest extends JavaOSGiTest {
}
@Override
public EventFilter getEventFilter() {
public @Nullable EventFilter getEventFilter() {
return null;
}
});
@ -178,7 +181,7 @@ public class RuntimeRuleTest extends JavaOSGiTest {
}
@Override
public EventFilter getEventFilter() {
public @Nullable EventFilter getEventFilter() {
return null;
}
});
@ -219,7 +222,7 @@ public class RuntimeRuleTest extends JavaOSGiTest {
}
private void assertSatisfiedHandlerInput(final CompareConditionHandler handler, final boolean expected,
final Object input) {
final @Nullable Object input) {
final boolean is = handler.isSatisfied(Collections.singletonMap("input", input));
if (expected) {
Assert.assertTrue(is);
@ -390,7 +393,7 @@ public class RuntimeRuleTest extends JavaOSGiTest {
}
@Override
public EventFilter getEventFilter() {
public @Nullable EventFilter getEventFilter() {
return null;
}
});

View File

@ -21,6 +21,7 @@ import java.util.Collection;
import javax.measure.quantity.Length;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -45,6 +46,7 @@ import org.openhab.core.types.State;
*
* @author Henning Treu - Initial contribution
*/
@NonNullByDefault
public class ScriptEngineOSGiTest extends JavaOSGiTest {
private static final String ITEM_NAME = "Switch1";
@ -52,11 +54,9 @@ public class ScriptEngineOSGiTest extends JavaOSGiTest {
private static final String NUMBER_ITEM_DECIMAL = "NumberB";
private static final String NUMBER_ITEM_LENGTH = "NumberC";
private ItemProvider itemProvider;
private ScriptEngine scriptEngine;
private ItemRegistry itemRegistry;
private @NonNullByDefault({}) ItemProvider itemProvider;
private @NonNullByDefault({}) ItemRegistry itemRegistry;
private @NonNullByDefault({}) ScriptEngine scriptEngine;
@Before
public void setup() {

View File

@ -22,6 +22,8 @@ import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.util.Collection;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -43,6 +45,7 @@ import org.openhab.core.thing.link.ItemChannelLinkRegistry;
*
* @author Simon Kaufmann - Initial contribution and API
*/
@NonNullByDefault
public class GenericItemChannelLinkProviderJavaTest extends JavaOSGiTest {
private static final String THINGS_TESTMODEL_NAME = "test.things";
@ -52,14 +55,13 @@ public class GenericItemChannelLinkProviderJavaTest extends JavaOSGiTest {
private static final String CHANNEL = "test:test:test:test";
private static final String LINK = ITEM + " -> " + CHANNEL;
private ModelRepository modelRepository;
private ThingRegistry thingRegistry;
private ItemRegistry itemRegistry;
private ItemChannelLinkRegistry itemChannelLinkRegistry;
private ItemChannelLinkProvider itemChannelLinkProvider;
private @Mock @Nullable ProviderChangeListener<ItemChannelLink> listenerMock;
@Mock
private ProviderChangeListener<ItemChannelLink> listener;
private @NonNullByDefault({}) ModelRepository modelRepository;
private @NonNullByDefault({}) ThingRegistry thingRegistry;
private @NonNullByDefault({}) ItemRegistry itemRegistry;
private @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistry;
private @NonNullByDefault({}) ItemChannelLinkProvider itemChannelLinkProvider;
@Before
public void setUp() {
@ -137,29 +139,38 @@ public class GenericItemChannelLinkProviderJavaTest extends JavaOSGiTest {
@Test
public void testNoAmnesia() throws Exception {
GenericItemChannelLinkProvider provider = new GenericItemChannelLinkProvider();
provider.addProviderChangeListener(listener);
ProviderChangeListener<ItemChannelLink> localListenerMock = listenerMock;
if (localListenerMock != null) {
provider.addProviderChangeListener(localListenerMock);
} else {
throw new IllegalStateException("listenerMock is null");
}
provider.startConfigurationUpdate(ITEMS_TESTMODEL_NAME);
provider.processBindingConfiguration(ITEMS_TESTMODEL_NAME, "Number", ITEM, CHANNEL, new Configuration());
provider.stopConfigurationUpdate(ITEMS_TESTMODEL_NAME);
assertThat(provider.getAll().size(), is(1));
assertThat(provider.getAll().iterator().next().toString(), is(LINK));
verify(listener, only()).added(same(provider), eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))));
verify(localListenerMock, only()).added(same(provider), eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))));
reset(listener);
reset(localListenerMock);
provider.startConfigurationUpdate(ITEMS_TESTMODEL_NAME);
provider.processBindingConfiguration(ITEMS_TESTMODEL_NAME, "Number", ITEM, CHANNEL, new Configuration());
provider.stopConfigurationUpdate(ITEMS_TESTMODEL_NAME);
assertThat(provider.getAll().size(), is(1));
assertThat(provider.getAll().iterator().next().toString(), is(LINK));
verify(listener, only()).updated(same(provider), eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))),
verify(localListenerMock, only()).updated(same(provider),
eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))),
eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))));
reset(listener);
reset(localListenerMock);
provider.startConfigurationUpdate(ITEMS_TESTMODEL_NAME);
provider.stopConfigurationUpdate(ITEMS_TESTMODEL_NAME);
assertThat(provider.getAll().size(), is(0));
verify(listener, only()).removed(same(provider), eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))));
verify(localListenerMock, only()).removed(same(provider),
eq(new ItemChannelLink(ITEM, new ChannelUID(CHANNEL))));
}
@Test

View File

@ -17,6 +17,8 @@ import static org.junit.Assert.*;
import java.util.Collection;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -35,6 +37,7 @@ import org.openhab.core.thing.binding.builder.ThingBuilder;
* @author Oliver Libutzki - Initial contribution
* @author Wouter Born - Migrate tests from Groovy to Java
*/
@NonNullByDefault
public class ManagedThingProviderOSGiTest extends JavaOSGiTest {
private static final String BINDIND_ID = "testBinding";
@ -43,8 +46,8 @@ public class ManagedThingProviderOSGiTest extends JavaOSGiTest {
private static final String THING1_ID = "testThing1";
private static final String THING2_ID = "testThing2";
private ManagedThingProvider managedThingProvider;
private ProviderChangeListener<Thing> thingChangeListener;
private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
private @NonNullByDefault({}) ProviderChangeListener<@NonNull Thing> thingChangeListener;
@Before
public void setup() {
@ -60,7 +63,7 @@ public class ManagedThingProviderOSGiTest extends JavaOSGiTest {
managedThingProvider.getAll().forEach(t -> managedThingProvider.remove(t.getUID()));
}
private void registerThingsChangeListener(ProviderChangeListener<Thing> thingChangeListener) {
private void registerThingsChangeListener(ProviderChangeListener<@NonNull Thing> thingChangeListener) {
unregisterCurrentThingsChangeListener();
this.thingChangeListener = thingChangeListener;
managedThingProvider.addProviderChangeListener(this.thingChangeListener);

View File

@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
@ -81,25 +82,24 @@ import org.osgi.service.component.ComponentContext;
*
* @author Christoph Weitkamp - Initial contribution
*/
@NonNullByDefault
public class ChannelCommandDescriptionProviderOSGiTest extends JavaOSGiTest {
private static final String TEST_BUNDLE_NAME = "thingStatusInfoI18nTest.bundle";
private static final ChannelTypeUID CHANNEL_TYPE_UID = new ChannelTypeUID("hue:dynamic");
private ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
private ItemRegistry itemRegistry;
private ItemChannelLinkRegistry linkRegistry;
private @Mock @NonNullByDefault({}) ComponentContext componentContextMock;
@Mock
private ComponentContext componentContext;
private Bundle testBundle;
private @NonNullByDefault({}) ItemRegistry itemRegistry;
private @NonNullByDefault({}) ItemChannelLinkRegistry linkRegistry;
private @NonNullByDefault({}) Bundle testBundle;
private @NonNullByDefault({}) ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
@Before
public void setup() throws Exception {
initMocks(this);
Mockito.when(componentContext.getBundleContext()).thenReturn(bundleContext);
Mockito.when(componentContextMock.getBundleContext()).thenReturn(bundleContext);
registerVolatileStorageService();
@ -107,7 +107,7 @@ public class ChannelCommandDescriptionProviderOSGiTest extends JavaOSGiTest {
assertNotNull(itemRegistry);
final TestThingHandlerFactory thingHandlerFactory = new TestThingHandlerFactory();
thingHandlerFactory.activate(componentContext);
thingHandlerFactory.activate(componentContextMock);
registerService(thingHandlerFactory, ThingHandlerFactory.class.getName());
final StateDescription state = StateDescriptionFragmentBuilder.create().withMinimum(BigDecimal.ZERO)
@ -132,12 +132,12 @@ public class ChannelCommandDescriptionProviderOSGiTest extends JavaOSGiTest {
registerService(new ChannelTypeProvider() {
@Override
public Collection<ChannelType> getChannelTypes(Locale locale) {
public Collection<ChannelType> getChannelTypes(@Nullable Locale locale) {
return channelTypes;
}
@Override
public ChannelType getChannelType(ChannelTypeUID channelTypeUID, Locale locale) {
public @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID, @Nullable Locale locale) {
for (final ChannelType channelType : channelTypes) {
if (channelType.getUID().equals(channelTypeUID)) {
return channelType;
@ -337,7 +337,7 @@ public class ChannelCommandDescriptionProviderOSGiTest extends JavaOSGiTest {
}
@Override
protected ThingHandler createHandler(Thing thing) {
protected @Nullable ThingHandler createHandler(Thing thing) {
return new AbstractThingHandler(thing) {
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
@ -385,7 +385,7 @@ public class ChannelCommandDescriptionProviderOSGiTest extends JavaOSGiTest {
*/
private class BundleResolverImpl implements BundleResolver {
@Override
public Bundle resolveBundle(Class<?> clazz) {
public Bundle resolveBundle(@NonNullByDefault({}) Class<?> clazz) {
if (clazz != null && clazz.equals(AbstractThingHandler.class)) {
return testBundle;
} else {

View File

@ -24,6 +24,7 @@ import java.util.stream.Stream;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@ -82,6 +83,7 @@ import org.openhab.core.types.StateDescriptionFragmentBuilder;
*
* @author Simon Kaufmann - Initial contribution
*/
@NonNullByDefault
public class CommunicationManagerOSGiTest extends JavaOSGiTest {
private class ItemChannelLinkRegistryAdvanced extends ItemChannelLinkRegistry {
@ -130,39 +132,19 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
ChannelBuilder.create(TRIGGER_CHANNEL_UID_1, "").withKind(ChannelKind.TRIGGER).build(),
ChannelBuilder.create(TRIGGER_CHANNEL_UID_2, "").withKind(ChannelKind.TRIGGER).build()).build();
private CommunicationManager manager;
private @Mock @NonNullByDefault({}) AutoUpdateManager autoUpdateManagerMock;
private @Mock @NonNullByDefault({}) ChannelTypeRegistry channelTypeRegistryMock;
private @Mock @NonNullByDefault({}) EventPublisher eventPublisherMock;
private @Mock @NonNullByDefault({}) ItemRegistry itemRegistryMock;
private @Mock @NonNullByDefault({}) ProfileAdvisor profileAdvisorMock;
private @Mock @NonNullByDefault({}) ProfileFactory profileFactoryMock;
private @Mock @NonNullByDefault({}) StateProfile stateProfileMock;
private @Mock @NonNullByDefault({}) ThingHandler thingHandlerMock;
private @Mock @NonNullByDefault({}) ThingRegistry thingRegistryMock;
private @Mock @NonNullByDefault({}) TriggerProfile triggerProfileMock;
@Mock
private ProfileFactory mockProfileFactory;
@Mock
private ProfileAdvisor mockProfileAdvisor;
@Mock
private StateProfile stateProfile;
@Mock
private TriggerProfile triggerProfile;
@Mock
private EventPublisher eventPublisher;
@Mock
private ItemRegistry itemRegistry;
@Mock
private ThingRegistry thingRegistry;
@Mock
private ThingHandler mockHandler;
@Mock
private AutoUpdateManager mockAutoUpdateManager;
@Mock
private ChannelTypeRegistry channelTypeRegistry;
private SafeCaller safeCaller;
private @NonNullByDefault({}) CommunicationManager manager;
private @NonNullByDefault({}) SafeCaller safeCaller;
@Before
public void setup() {
@ -175,7 +157,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
assertNotNull(profileFactory);
manager = new CommunicationManager();
manager.setEventPublisher(eventPublisher);
manager.setEventPublisher(eventPublisherMock);
manager.setDefaultProfileFactory(profileFactory);
manager.setSafeCaller(safeCaller);
@ -187,25 +169,26 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
return new ProfileTypeUID("test:trigger");
}
return null;
}).when(mockProfileAdvisor).getSuggestedProfileTypeUID(isA(Channel.class), isA(String.class));
}).when(profileAdvisorMock).getSuggestedProfileTypeUID(isA(Channel.class), isA(String.class));
doAnswer(invocation -> {
switch (((ProfileTypeUID) invocation.getArguments()[0]).toString()) {
case "test:state":
return stateProfile;
return stateProfileMock;
case "test:trigger":
return triggerProfile;
return triggerProfileMock;
}
return null;
}).when(mockProfileFactory).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
}).when(profileFactoryMock).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
when(mockProfileFactory.getSupportedProfileTypeUIDs()).thenReturn(Stream
when(profileFactoryMock.getSupportedProfileTypeUIDs()).thenReturn(Stream
.of(new ProfileTypeUID("test:state"), new ProfileTypeUID("test:trigger")).collect(Collectors.toList()));
manager.addProfileFactory(mockProfileFactory);
manager.addProfileAdvisor(mockProfileAdvisor);
manager.addProfileFactory(profileFactoryMock);
manager.addProfileAdvisor(profileAdvisorMock);
ItemChannelLinkRegistryAdvanced iclRegistry = new ItemChannelLinkRegistryAdvanced(thingRegistry, itemRegistry);
ItemChannelLinkRegistryAdvanced iclRegistry = new ItemChannelLinkRegistryAdvanced(thingRegistryMock,
itemRegistryMock);
iclRegistry.addProvider(new ItemChannelLinkProvider() {
@Override
public void addProviderChangeListener(ProviderChangeListener<ItemChannelLink> listener) {
@ -223,24 +206,24 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
});
manager.setItemChannelLinkRegistry(iclRegistry);
when(itemRegistry.get(eq(ITEM_NAME_1))).thenReturn(ITEM_1);
when(itemRegistry.get(eq(ITEM_NAME_2))).thenReturn(ITEM_2);
when(itemRegistry.get(eq(ITEM_NAME_3))).thenReturn(ITEM_3);
when(itemRegistry.get(eq(ITEM_NAME_4))).thenReturn(ITEM_4);
manager.setItemRegistry(itemRegistry);
when(itemRegistryMock.get(eq(ITEM_NAME_1))).thenReturn(ITEM_1);
when(itemRegistryMock.get(eq(ITEM_NAME_2))).thenReturn(ITEM_2);
when(itemRegistryMock.get(eq(ITEM_NAME_3))).thenReturn(ITEM_3);
when(itemRegistryMock.get(eq(ITEM_NAME_4))).thenReturn(ITEM_4);
manager.setItemRegistry(itemRegistryMock);
ChannelType channelType4 = mock(ChannelType.class);
when(channelType4.getItemType()).thenReturn("Number:Temperature");
when(channelTypeRegistry.getChannelType(CHANNEL_TYPE_UID_4)).thenReturn(channelType4);
manager.setChannelTypeRegistry(channelTypeRegistry);
when(channelTypeRegistryMock.getChannelType(CHANNEL_TYPE_UID_4)).thenReturn(channelType4);
manager.setChannelTypeRegistry(channelTypeRegistryMock);
THING.setHandler(mockHandler);
THING.setHandler(thingHandlerMock);
when(thingRegistry.get(eq(THING_UID))).thenReturn(THING);
manager.setThingRegistry(thingRegistry);
when(thingRegistryMock.get(eq(THING_UID))).thenReturn(THING);
manager.setThingRegistry(thingRegistryMock);
manager.addItemFactory(new CoreItemFactory());
manager.setAutoUpdateManager(mockAutoUpdateManager);
manager.setAutoUpdateManager(autoUpdateManagerMock);
UnitProvider unitProvider = mock(UnitProvider.class);
when(unitProvider.getUnit(Temperature.class)).thenReturn(SIUnits.CELSIUS);
@ -252,51 +235,51 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
public void testStateUpdatedSingleLink() {
manager.stateUpdated(STATE_CHANNEL_UID_1, OnOffType.ON);
waitForAssert(() -> {
verify(stateProfile).onStateUpdateFromHandler(eq(OnOffType.ON));
verify(stateProfileMock).onStateUpdateFromHandler(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testStateUpdatedMultiLink() {
manager.stateUpdated(STATE_CHANNEL_UID_2, OnOffType.ON);
waitForAssert(() -> {
verify(stateProfile, times(2)).onStateUpdateFromHandler(eq(OnOffType.ON));
verify(stateProfileMock, times(2)).onStateUpdateFromHandler(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testPostCommandSingleLink() {
manager.postCommand(STATE_CHANNEL_UID_1, OnOffType.ON);
waitForAssert(() -> {
verify(stateProfile).onCommandFromHandler(eq(OnOffType.ON));
verify(stateProfileMock).onCommandFromHandler(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testPostCommandMultiLink() {
manager.postCommand(STATE_CHANNEL_UID_2, OnOffType.ON);
waitForAssert(() -> {
verify(stateProfile, times(2)).onCommandFromHandler(eq(OnOffType.ON));
verify(stateProfileMock, times(2)).onCommandFromHandler(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testItemCommandEventSingleLink() {
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_2, OnOffType.ON));
waitForAssert(() -> {
verify(stateProfile).onCommandFromItem(eq(OnOffType.ON));
verify(stateProfileMock).onCommandFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verify(mockAutoUpdateManager).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
verify(autoUpdateManagerMock).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
}
@Test
@ -304,10 +287,10 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
// Take unit from accepted item type (see channel built from STATE_CHANNEL_UID_3)
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_3, DecimalType.valueOf("20")));
waitForAssert(() -> {
verify(stateProfile).onCommandFromItem(eq(QuantityType.valueOf("20 °C")));
verify(stateProfileMock).onCommandFromItem(eq(QuantityType.valueOf("20 °C")));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
@ -320,10 +303,10 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_3, DecimalType.valueOf("20")));
waitForAssert(() -> {
verify(stateProfile).onCommandFromItem(eq(QuantityType.valueOf("20 °F")));
verify(stateProfileMock).onCommandFromItem(eq(QuantityType.valueOf("20 °F")));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
ITEM_3.setStateDescriptionService(null);
}
@ -335,21 +318,21 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
// current ThingType.
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_4, DecimalType.valueOf("20")));
waitForAssert(() -> {
verify(stateProfile).onCommandFromItem(eq(QuantityType.valueOf("20 °C")));
verify(stateProfileMock).onCommandFromItem(eq(QuantityType.valueOf("20 °C")));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testItemCommandEventMultiLink() {
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_1, OnOffType.ON));
waitForAssert(() -> {
verify(stateProfile, times(2)).onCommandFromItem(eq(OnOffType.ON));
verify(stateProfileMock, times(2)).onCommandFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verify(mockAutoUpdateManager).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
verify(autoUpdateManagerMock).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
}
@Test
@ -357,33 +340,33 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
manager.receive(
ItemEventFactory.createCommandEvent(ITEM_NAME_1, OnOffType.ON, STATE_CHANNEL_UID_2.getAsString()));
waitForAssert(() -> {
verify(stateProfile).onCommandFromItem(eq(OnOffType.ON));
verify(stateProfileMock).onCommandFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verify(mockAutoUpdateManager).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
verify(autoUpdateManagerMock).receiveCommand(isA(ItemCommandEvent.class), isA(Item.class));
}
@Test
public void testItemStateEventSingleLink() {
manager.receive(ItemEventFactory.createStateEvent(ITEM_NAME_2, OnOffType.ON));
waitForAssert(() -> {
verify(stateProfile).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfile).onStateUpdateFromItem(eq(OnOffType.ON));
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testItemStateEventMultiLink() {
manager.receive(ItemEventFactory.createStateEvent(ITEM_NAME_1, OnOffType.ON));
waitForAssert(() -> {
verify(stateProfile, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfile, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
verify(stateProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
@ -391,31 +374,31 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
manager.receive(
ItemEventFactory.createStateEvent(ITEM_NAME_1, OnOffType.ON, STATE_CHANNEL_UID_2.getAsString()));
waitForAssert(() -> {
verify(stateProfile).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfile, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testChannelTriggeredEventSingleLink() {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_1));
waitForAssert(() -> {
verify(triggerProfile).onTriggerFromHandler(eq(EVENT));
verify(triggerProfileMock).onTriggerFromHandler(eq(EVENT));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
public void testChannelTriggeredEventMultiLink() {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_2));
waitForAssert(() -> {
verify(triggerProfile, times(2)).onTriggerFromHandler(eq(EVENT));
verify(triggerProfileMock, times(2)).onTriggerFromHandler(eq(EVENT));
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
@ -425,13 +408,13 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
}
waitForAssert(() -> {
verify(mockProfileFactory, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
verify(mockProfileFactory, atLeast(0)).getSupportedProfileTypeUIDs();
verify(mockProfileAdvisor, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
verify(profileFactoryMock, atLeast(0)).getSupportedProfileTypeUIDs();
verify(profileAdvisorMock, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
});
verifyNoMoreInteractions(mockProfileFactory);
verifyNoMoreInteractions(mockProfileAdvisor);
verifyNoMoreInteractions(profileFactoryMock);
verifyNoMoreInteractions(profileAdvisorMock);
}
@Test
@ -439,24 +422,24 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
for (int i = 0; i < 3; i++) {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_2));
}
verify(mockProfileFactory, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
manager.removeProfileFactory(mockProfileFactory);
manager.addProfileFactory(mockProfileFactory);
manager.removeProfileFactory(profileFactoryMock);
manager.addProfileFactory(profileFactoryMock);
for (int i = 0; i < 3; i++) {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_2));
}
waitForAssert(() -> {
verify(mockProfileFactory, times(4)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(4)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
verify(mockProfileFactory, atLeast(0)).getSupportedProfileTypeUIDs();
verify(mockProfileAdvisor, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
verify(profileFactoryMock, atLeast(0)).getSupportedProfileTypeUIDs();
verify(profileAdvisorMock, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
});
verifyNoMoreInteractions(mockProfileFactory);
verifyNoMoreInteractions(mockProfileAdvisor);
verifyNoMoreInteractions(profileFactoryMock);
verifyNoMoreInteractions(profileAdvisorMock);
}
@Test
@ -465,7 +448,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_2));
}
waitForAssert(() -> {
verify(mockProfileFactory, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
});
@ -477,13 +460,13 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
}
waitForAssert(() -> {
verify(mockProfileFactory, times(3)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(3)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
verify(mockProfileFactory, atLeast(0)).getSupportedProfileTypeUIDs();
verify(mockProfileAdvisor, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
verify(profileFactoryMock, atLeast(0)).getSupportedProfileTypeUIDs();
verify(profileAdvisorMock, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
});
verifyNoMoreInteractions(mockProfileFactory);
verifyNoMoreInteractions(mockProfileAdvisor);
verifyNoMoreInteractions(profileFactoryMock);
verifyNoMoreInteractions(profileAdvisorMock);
}
@Test
@ -500,13 +483,13 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
}
waitForAssert(() -> {
verify(mockProfileFactory, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
verify(mockProfileFactory, atLeast(0)).getSupportedProfileTypeUIDs();
verify(mockProfileAdvisor, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
verify(profileFactoryMock, atLeast(0)).getSupportedProfileTypeUIDs();
verify(profileAdvisorMock, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
});
verifyNoMoreInteractions(mockProfileFactory);
verifyNoMoreInteractions(mockProfileAdvisor);
verifyNoMoreInteractions(profileFactoryMock);
verifyNoMoreInteractions(profileAdvisorMock);
}
@Test
@ -514,7 +497,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
for (int i = 0; i < 3; i++) {
manager.receive(ThingEventFactory.createTriggerEvent(EVENT, TRIGGER_CHANNEL_UID_2));
}
verify(mockProfileFactory, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(2)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
manager.updated(LINK_2_T2, LINK_2_T2);
@ -524,13 +507,13 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
}
waitForAssert(() -> {
verify(mockProfileFactory, times(3)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
verify(profileFactoryMock, times(3)).createProfile(isA(ProfileTypeUID.class), isA(ProfileCallback.class),
isA(ProfileContext.class));
verify(mockProfileFactory, atLeast(0)).getSupportedProfileTypeUIDs();
verify(mockProfileAdvisor, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
verify(profileFactoryMock, atLeast(0)).getSupportedProfileTypeUIDs();
verify(profileAdvisorMock, atLeast(0)).getSuggestedProfileTypeUID(any(Channel.class), any());
});
verifyNoMoreInteractions(mockProfileFactory);
verifyNoMoreInteractions(mockProfileAdvisor);
verifyNoMoreInteractions(profileFactoryMock);
verifyNoMoreInteractions(profileAdvisorMock);
}
@Test
@ -538,19 +521,19 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
Thing thing = ThingBuilder.create(THING_TYPE_UID, THING_UID)
.withChannels(ChannelBuilder.create(STATE_CHANNEL_UID_2, "Dimmer").withKind(ChannelKind.STATE).build())
.build();
thing.setHandler(mockHandler);
when(thingRegistry.get(eq(THING_UID))).thenReturn(thing);
thing.setHandler(thingHandlerMock);
when(thingRegistryMock.get(eq(THING_UID))).thenReturn(thing);
manager.receive(ItemEventFactory.createCommandEvent(ITEM_NAME_2, HSBType.fromRGB(128, 128, 128)));
waitForAssert(() -> {
ArgumentCaptor<Command> commandCaptor = ArgumentCaptor.forClass(Command.class);
verify(stateProfile).onCommandFromItem(commandCaptor.capture());
verify(stateProfileMock).onCommandFromItem(commandCaptor.capture());
Command command = commandCaptor.getValue();
assertNotNull(command);
assertEquals(PercentType.class, command.getClass());
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
@Test
@ -558,19 +541,19 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
Thing thing = ThingBuilder.create(THING_TYPE_UID, THING_UID)
.withChannels(ChannelBuilder.create(STATE_CHANNEL_UID_2, "Dimmer").withKind(ChannelKind.STATE).build())
.build();
thing.setHandler(mockHandler);
when(thingRegistry.get(eq(THING_UID))).thenReturn(thing);
thing.setHandler(thingHandlerMock);
when(thingRegistryMock.get(eq(THING_UID))).thenReturn(thing);
manager.receive(ItemEventFactory.createStateEvent(ITEM_NAME_2, HSBType.fromRGB(128, 128, 128)));
waitForAssert(() -> {
ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
verify(stateProfile).onStateUpdateFromItem(stateCaptor.capture());
verify(stateProfileMock).onStateUpdateFromItem(stateCaptor.capture());
State state = stateCaptor.getValue();
assertNotNull(state);
assertEquals(PercentType.class, state.getClass());
});
verifyNoMoreInteractions(stateProfile);
verifyNoMoreInteractions(triggerProfile);
verifyNoMoreInteractions(stateProfileMock);
verifyNoMoreInteractions(triggerProfileMock);
}
}