diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AbstractMQTTThingHandler.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AbstractMQTTThingHandler.java index e7ff415f4..b9f932c6d 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AbstractMQTTThingHandler.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AbstractMQTTThingHandler.java @@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.values.OnOffValue; @@ -327,8 +326,8 @@ public abstract class AbstractMQTTThingHandler extends BaseThingHandler } @Override - public void removeAvailabilityTopic(@NonNull String availability_topic) { - availabilityStates.computeIfPresent(availability_topic, (topic, state) -> { + public void removeAvailabilityTopic(String availabilityTopic) { + availabilityStates.computeIfPresent(availabilityTopic, (topic, state) -> { if (connection != null && state != null) { state.stop(); } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/ColorMode.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/ColorMode.java index 131cdbeef..db2d60c33 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/ColorMode.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/ColorMode.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.mqtt.generic.mapping; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Color modes supported by the binding. * * @author Aitor Iturrioz - Initial contribution */ +@NonNullByDefault public enum ColorMode { HSB, RGB, diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopic.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopic.java index ca1d386c8..de416e07c 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopic.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopic.java @@ -81,13 +81,13 @@ public class SubscribeFieldToMQTTtopic implements MqttMessageSubscriber { String typeName = type.getSimpleName(); if (value instanceof BigDecimal && !type.equals(BigDecimal.class)) { BigDecimal bdValue = (BigDecimal) value; - if (type.equals(Float.class) || typeName.equals("float")) { + if (type.equals(Float.class) || "float".equals(typeName)) { result = bdValue.floatValue(); - } else if (type.equals(Double.class) || typeName.equals("double")) { + } else if (type.equals(Double.class) || "double".equals(typeName)) { result = bdValue.doubleValue(); - } else if (type.equals(Long.class) || typeName.equals("long")) { + } else if (type.equals(Long.class) || "long".equals(typeName)) { result = bdValue.longValue(); - } else if (type.equals(Integer.class) || typeName.equals("int")) { + } else if (type.equals(Integer.class) || "int".equals(typeName)) { result = bdValue.intValue(); } } else @@ -95,17 +95,17 @@ public class SubscribeFieldToMQTTtopic implements MqttMessageSubscriber { // primitive types if (value instanceof String && !type.equals(String.class)) { String bdValue = (String) value; - if (type.equals(Float.class) || typeName.equals("float")) { + if (type.equals(Float.class) || "float".equals(typeName)) { result = Float.valueOf(bdValue); - } else if (type.equals(Double.class) || typeName.equals("double")) { + } else if (type.equals(Double.class) || "double".equals(typeName)) { result = Double.valueOf(bdValue); - } else if (type.equals(Long.class) || typeName.equals("long")) { + } else if (type.equals(Long.class) || "long".equals(typeName)) { result = Long.valueOf(bdValue); } else if (type.equals(BigDecimal.class)) { result = new BigDecimal(bdValue); - } else if (type.equals(Integer.class) || typeName.equals("int")) { + } else if (type.equals(Integer.class) || "int".equals(typeName)) { result = Integer.valueOf(bdValue); - } else if (type.equals(Boolean.class) || typeName.equals("boolean")) { + } else if (type.equals(Boolean.class) || "boolean".equals(typeName)) { result = Boolean.valueOf(bdValue); } else if (type.isEnum()) { @SuppressWarnings({ "rawtypes", "unchecked" }) diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/utils/FutureCollector.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/utils/FutureCollector.java index c63aa2acf..c3e0513dd 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/utils/FutureCollector.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/utils/FutureCollector.java @@ -18,21 +18,24 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import java.util.stream.Collector; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Collector to combine a stream of CompletableFutures. * * @author Jochen Klein - Initial contribution * */ +@NonNullByDefault public class FutureCollector { - public static Collector, Set>, CompletableFuture> allOf() { - return Collector., Set>, CompletableFuture> of( + public static Collector, Set>, CompletableFuture<@Nullable Void>> allOf() { + return Collector., Set>, CompletableFuture<@Nullable Void>> of( (Supplier>>) HashSet::new, Set::add, (left, right) -> { left.addAll(right); return left; - }, a -> { - return CompletableFuture.allOf(a.toArray(new CompletableFuture[a.size()])); - }, Collector.Characteristics.UNORDERED); + }, a -> CompletableFuture.allOf(a.toArray(new CompletableFuture[a.size()])), + Collector.Characteristics.UNORDERED); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ColorValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ColorValue.java index f846b111f..df8ac6888 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ColorValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ColorValue.java @@ -13,9 +13,8 @@ package org.openhab.binding.mqtt.generic.values; import java.math.BigDecimal; +import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.ws.rs.NotSupportedException; @@ -63,8 +62,7 @@ public class ColorValue extends Value { * @param onBrightness When receiving a ON command, the brightness percentage is set to this value */ public ColorValue(ColorMode colorMode, @Nullable String onValue, @Nullable String offValue, int onBrightness) { - super(CoreItemFactory.COLOR, - Stream.of(OnOffType.class, PercentType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.COLOR, List.of(OnOffType.class, PercentType.class, StringType.class)); if (onBrightness > 100) { throw new IllegalArgumentException("Brightness parameter must be <= 100"); @@ -112,8 +110,8 @@ public class ColorValue extends Value { Integer.parseInt(split[2])); break; case XYY: - HSBType temp_state = HSBType.fromXY(Float.parseFloat(split[0]), Float.parseFloat(split[1])); - state = new HSBType(temp_state.getHue(), temp_state.getSaturation(), new PercentType(split[2])); + HSBType tempState = HSBType.fromXY(Float.parseFloat(split[0]), Float.parseFloat(split[1])); + state = new HSBType(tempState.getHue(), tempState.getSaturation(), new PercentType(split[2])); break; default: logger.warn("Non supported color mode"); @@ -146,21 +144,21 @@ public class ColorValue extends Value { } } - HSBType hsb_state = (HSBType) state; + HSBType hsbState = (HSBType) state; switch (this.colorMode) { case HSB: - return String.format(formatPattern, hsb_state.getHue().intValue(), hsb_state.getSaturation().intValue(), - hsb_state.getBrightness().intValue()); + return String.format(formatPattern, hsbState.getHue().intValue(), hsbState.getSaturation().intValue(), + hsbState.getBrightness().intValue()); case RGB: - PercentType[] rgb = hsb_state.toRGB(); + PercentType[] rgb = hsbState.toRGB(); return String.format(formatPattern, rgb[0].toBigDecimal().multiply(factor).intValue(), rgb[1].toBigDecimal().multiply(factor).intValue(), rgb[2].toBigDecimal().multiply(factor).intValue()); case XYY: - PercentType[] xyY = hsb_state.toXY(); + PercentType[] xyY = hsbState.toXY(); return String.format(Locale.ROOT, formatPattern, xyY[0].floatValue() / 100.0f, - xyY[1].floatValue() / 100.0f, hsb_state.getBrightness().floatValue()); + xyY[1].floatValue() / 100.0f, hsbState.getBrightness().floatValue()); default: throw new NotSupportedException(String.format("Non supported color mode: {}", this.colorMode)); } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java index 3fcbb37d7..916f8174e 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java @@ -13,8 +13,7 @@ package org.openhab.binding.mqtt.generic.values; import java.time.format.DateTimeFormatter; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -32,7 +31,7 @@ import org.openhab.core.types.UnDefType; @NonNullByDefault public class DateTimeValue extends Value { public DateTimeValue() { - super(CoreItemFactory.DATETIME, Stream.of(DateTimeType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.DATETIME, List.of(DateTimeType.class, StringType.class)); } @Override diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ImageValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ImageValue.java index 0294f4f52..2eb81f3ac 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ImageValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ImageValue.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.mqtt.generic.values; -import java.util.Collections; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.library.CoreItemFactory; @@ -26,7 +26,7 @@ import org.openhab.core.types.Command; @NonNullByDefault public class ImageValue extends Value { public ImageValue() { - super(CoreItemFactory.IMAGE, Collections.emptyList()); + super(CoreItemFactory.IMAGE, List.of()); } @Override diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/LocationValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/LocationValue.java index 7186dbbe1..322dff58e 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/LocationValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/LocationValue.java @@ -13,11 +13,9 @@ package org.openhab.binding.mqtt.generic.values; import java.math.BigDecimal; +import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.CoreItemFactory; @@ -33,11 +31,11 @@ import org.openhab.core.types.Command; @NonNullByDefault public class LocationValue extends Value { public LocationValue() { - super(CoreItemFactory.LOCATION, Stream.of(PointType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.LOCATION, List.of(PointType.class, StringType.class)); } @Override - public @NonNull String getMQTTpublishValue(@Nullable String pattern) { + public String getMQTTpublishValue(@Nullable String pattern) { String formatPattern = pattern; PointType point = ((PointType) state); diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java index de6f5c6f2..26e352dce 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java @@ -13,8 +13,7 @@ package org.openhab.binding.mqtt.generic.values; import java.math.BigDecimal; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import javax.measure.Unit; @@ -53,8 +52,7 @@ public class NumberValue extends Value { public NumberValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step, @Nullable Unit unit) { - super(CoreItemFactory.NUMBER, Stream.of(QuantityType.class, IncreaseDecreaseType.class, UpDownType.class) - .collect(Collectors.toList())); + super(CoreItemFactory.NUMBER, List.of(QuantityType.class, IncreaseDecreaseType.class, UpDownType.class)); this.min = min; this.max = max; this.step = step == null ? BigDecimal.ONE : step; diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OnOffValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OnOffValue.java index 67db43f76..d56eb1d66 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OnOffValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OnOffValue.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mqtt.generic.values; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -65,7 +64,7 @@ public class OnOffValue extends Value { */ public OnOffValue(@Nullable String onState, @Nullable String offState, @Nullable String onCommand, @Nullable String offCommand) { - super(CoreItemFactory.SWITCH, Stream.of(OnOffType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.SWITCH, List.of(OnOffType.class, StringType.class)); this.onState = onState == null ? OnOffType.ON.name() : onState; this.offState = offState == null ? OnOffType.OFF.name() : offState; this.onCommand = onCommand == null ? OnOffType.ON.name() : onCommand; diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OpenCloseValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OpenCloseValue.java index 1bc873dc2..556547647 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OpenCloseValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/OpenCloseValue.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mqtt.generic.values; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -36,7 +35,7 @@ public class OpenCloseValue extends Value { * Creates a contact Open/Close type. */ public OpenCloseValue() { - super(CoreItemFactory.CONTACT, Stream.of(OpenClosedType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.CONTACT, List.of(OpenClosedType.class, StringType.class)); this.openString = OpenClosedType.OPEN.name(); this.closeString = OpenClosedType.CLOSED.name(); } @@ -48,7 +47,7 @@ public class OpenCloseValue extends Value { * @param closeValue The OFF value string. This will be compared to MQTT messages. */ public OpenCloseValue(@Nullable String openValue, @Nullable String closeValue) { - super(CoreItemFactory.CONTACT, Stream.of(OpenClosedType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.CONTACT, List.of(OpenClosedType.class, StringType.class)); this.openString = openValue == null ? OpenClosedType.OPEN.name() : openValue; this.closeString = closeValue == null ? OpenClosedType.CLOSED.name() : closeValue; } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java index a8461e0a7..f9a537d44 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java @@ -14,8 +14,7 @@ package org.openhab.binding.mqtt.generic.values; import java.math.BigDecimal; import java.math.MathContext; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -58,8 +57,8 @@ public class PercentageValue extends Value { public PercentageValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step, @Nullable String onValue, @Nullable String offValue) { - super(CoreItemFactory.DIMMER, Stream.of(DecimalType.class, QuantityType.class, IncreaseDecreaseType.class, - OnOffType.class, UpDownType.class, StringType.class).collect(Collectors.toList())); + super(CoreItemFactory.DIMMER, List.of(DecimalType.class, QuantityType.class, IncreaseDecreaseType.class, + OnOffType.class, UpDownType.class, StringType.class)); this.onValue = onValue; this.offValue = offValue; this.min = min == null ? BigDecimal.ZERO : min; diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/RollershutterValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/RollershutterValue.java index f3fc46f3a..b8f37e05c 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/RollershutterValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/RollershutterValue.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mqtt.generic.values; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -51,8 +50,7 @@ public class RollershutterValue extends Value { */ public RollershutterValue(@Nullable String upString, @Nullable String downString, @Nullable String stopString) { super(CoreItemFactory.ROLLERSHUTTER, - Stream.of(UpDownType.class, StopMoveType.class, PercentType.class, StringType.class) - .collect(Collectors.toList())); + List.of(UpDownType.class, StopMoveType.class, PercentType.class, StringType.class)); this.upString = upString; this.downString = downString; this.stopString = stopString == null ? StopMoveType.STOP.name() : stopString; diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/TextValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/TextValue.java index f0f5e83c7..c184c5b57 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/TextValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/TextValue.java @@ -14,7 +14,7 @@ package org.openhab.binding.mqtt.generic.values; import static java.util.function.Predicate.not; -import java.util.Collections; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -45,7 +45,7 @@ public class TextValue extends Value { * will be allowed. */ public TextValue(String[] states) { - super(CoreItemFactory.STRING, Collections.singletonList(StringType.class)); + super(CoreItemFactory.STRING, List.of(StringType.class)); Set s = Stream.of(states).filter(not(String::isBlank)).collect(Collectors.toSet()); if (!s.isEmpty()) { this.states = s; @@ -55,7 +55,7 @@ public class TextValue extends Value { } public TextValue() { - super(CoreItemFactory.STRING, Collections.singletonList(StringType.class)); + super(CoreItemFactory.STRING, List.of(StringType.class)); this.states = null; } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java index 75a582261..c3b458dbf 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java @@ -24,12 +24,11 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -62,25 +61,26 @@ import org.openhab.core.thing.ChannelUID; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class ChannelStateTests { - private @Mock MqttBrokerConnection connection; - private @Mock ChannelStateUpdateListener channelStateUpdateListener; - private @Mock ChannelUID channelUID; - private @Spy TextValue textValue; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; + private @Mock @NonNullByDefault({}) ChannelStateUpdateListener channelStateUpdateListenerMock; + private @Mock @NonNullByDefault({}) ChannelUID channelUIDMock; + private @Spy @NonNullByDefault({}) TextValue textValue; - private ScheduledExecutorService scheduler; + private @NonNullByDefault({}) ScheduledExecutorService scheduler; private ChannelConfig config = ChannelConfigBuilder.create("state", "command").build(); @BeforeEach public void setUp() { - CompletableFuture voidFutureComplete = new CompletableFuture<>(); + CompletableFuture<@Nullable Void> voidFutureComplete = new CompletableFuture<>(); voidFutureComplete.complete(null); - doReturn(voidFutureComplete).when(connection).unsubscribeAll(); - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).publish(any(), any(), anyInt(), + doReturn(voidFutureComplete).when(connectionMock).unsubscribeAll(); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).publish(any(), any(), anyInt(), anyBoolean()); scheduler = new ScheduledThreadPoolExecutor(1); @@ -92,74 +92,74 @@ public class ChannelStateTests { } @Test - public void noInteractionTimeoutTest() throws InterruptedException, ExecutionException, TimeoutException { - ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener)); - c.start(connection, scheduler, 50).get(100, TimeUnit.MILLISECONDS); - verify(connection).subscribe(eq("state"), eq(c)); + public void noInteractionTimeoutTest() throws Exception { + ChannelState c = spy(new ChannelState(config, channelUIDMock, textValue, channelStateUpdateListenerMock)); + c.start(connectionMock, scheduler, 50).get(100, TimeUnit.MILLISECONDS); + verify(connectionMock).subscribe(eq("state"), eq(c)); c.stop().get(); - verify(connection).unsubscribe(eq("state"), eq(c)); + verify(connectionMock).unsubscribe(eq("state"), eq(c)); } @Test - public void publishFormatTest() throws InterruptedException, ExecutionException, TimeoutException { - ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener)); + public void publishFormatTest() throws Exception { + ChannelState c = spy(new ChannelState(config, channelUIDMock, textValue, channelStateUpdateListenerMock)); - c.start(connection, scheduler, 0).get(50, TimeUnit.MILLISECONDS); - verify(connection).subscribe(eq("state"), eq(c)); + c.start(connectionMock, scheduler, 0).get(50, TimeUnit.MILLISECONDS); + verify(connectionMock).subscribe(eq("state"), eq(c)); c.publishValue(new StringType("UPDATE")).get(); - verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE".getBytes())), anyInt(), + verify(connectionMock).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE".getBytes())), anyInt(), eq(false)); c.config.formatBeforePublish = "prefix%s"; c.publishValue(new StringType("UPDATE")).get(); - verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "prefixUPDATE".getBytes())), anyInt(), - eq(false)); + verify(connectionMock).publish(eq("command"), argThat(p -> Arrays.equals(p, "prefixUPDATE".getBytes())), + anyInt(), eq(false)); c.config.formatBeforePublish = "%1$s-%1$s"; c.publishValue(new StringType("UPDATE")).get(); - verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE-UPDATE".getBytes())), anyInt(), - eq(false)); + verify(connectionMock).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE-UPDATE".getBytes())), + anyInt(), eq(false)); c.config.formatBeforePublish = "%s"; c.config.retained = true; c.publishValue(new StringType("UPDATE")).get(); - verify(connection).publish(eq("command"), any(), anyInt(), eq(true)); + verify(connectionMock).publish(eq("command"), any(), anyInt(), eq(true)); c.stop().get(); - verify(connection).unsubscribe(eq("state"), eq(c)); + verify(connectionMock).unsubscribe(eq("state"), eq(c)); } @Test - public void receiveWildcardTest() throws InterruptedException, ExecutionException, TimeoutException { + public void receiveWildcardTest() throws Exception { ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(), - channelUID, textValue, channelStateUpdateListener)); + channelUIDMock, textValue, channelStateUpdateListenerMock)); - CompletableFuture<@Nullable Void> future = c.start(connection, scheduler, 100); + CompletableFuture<@Nullable Void> future = c.start(connectionMock, scheduler, 100); c.processMessage("state/bla/topic", "A TEST".getBytes()); future.get(300, TimeUnit.MILLISECONDS); assertThat(textValue.getChannelState().toString(), is("A TEST")); - verify(channelStateUpdateListener).updateChannelState(eq(channelUID), any()); + verify(channelStateUpdateListenerMock).updateChannelState(eq(channelUIDMock), any()); } @Test - public void receiveStringTest() throws InterruptedException, ExecutionException, TimeoutException { - ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener)); + public void receiveStringTest() throws Exception { + ChannelState c = spy(new ChannelState(config, channelUIDMock, textValue, channelStateUpdateListenerMock)); - CompletableFuture<@Nullable Void> future = c.start(connection, scheduler, 100); + CompletableFuture<@Nullable Void> future = c.start(connectionMock, scheduler, 100); c.processMessage("state", "A TEST".getBytes()); future.get(300, TimeUnit.MILLISECONDS); assertThat(textValue.getChannelState().toString(), is("A TEST")); - verify(channelStateUpdateListener).updateChannelState(eq(channelUID), any()); + verify(channelStateUpdateListenerMock).updateChannelState(eq(channelUIDMock), any()); } @Test public void receiveDecimalTest() { NumberValue value = new NumberValue(null, null, new BigDecimal(10), null); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "15".getBytes()); assertThat(value.getChannelState().toString(), is("15")); @@ -170,14 +170,14 @@ public class ChannelStateTests { c.processMessage("state", "DECREASE".getBytes()); assertThat(value.getChannelState().toString(), is("15")); - verify(channelStateUpdateListener, times(3)).updateChannelState(eq(channelUID), any()); + verify(channelStateUpdateListenerMock, times(3)).updateChannelState(eq(channelUIDMock), any()); } @Test public void receiveDecimalFractionalTest() { NumberValue value = new NumberValue(null, null, new BigDecimal(10.5), null); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "5.5".getBytes()); assertThat(value.getChannelState().toString(), is("5.5")); @@ -189,8 +189,8 @@ public class ChannelStateTests { @Test public void receiveDecimalUnitTest() { NumberValue value = new NumberValue(null, null, new BigDecimal(10), Units.WATT); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "15".getBytes()); assertThat(value.getChannelState().toString(), is("15 W")); @@ -201,27 +201,27 @@ public class ChannelStateTests { c.processMessage("state", "DECREASE".getBytes()); assertThat(value.getChannelState().toString(), is("15 W")); - verify(channelStateUpdateListener, times(3)).updateChannelState(eq(channelUID), any()); + verify(channelStateUpdateListenerMock, times(3)).updateChannelState(eq(channelUIDMock), any()); } @Test public void receiveDecimalAsPercentageUnitTest() { NumberValue value = new NumberValue(null, null, new BigDecimal(10), Units.PERCENT); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "63.7".getBytes()); assertThat(value.getChannelState().toString(), is("63.7 %")); - verify(channelStateUpdateListener, times(1)).updateChannelState(eq(channelUID), any()); + verify(channelStateUpdateListenerMock, times(1)).updateChannelState(eq(channelUIDMock), any()); } @Test public void receivePercentageTest() { PercentageValue value = new PercentageValue(new BigDecimal(-100), new BigDecimal(100), new BigDecimal(10), null, null); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "-100".getBytes()); // 0% assertThat(value.getChannelState().toString(), is("0")); @@ -241,8 +241,8 @@ public class ChannelStateTests { @Test public void receiveRGBColorTest() { ColorValue value = new ColorValue(ColorMode.RGB, "FON", "FOFF", 10); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "ON".getBytes()); // Normal on state assertThat(value.getChannelState().toString(), is("0,0,10")); @@ -268,8 +268,8 @@ public class ChannelStateTests { @Test public void receiveHSBColorTest() { ColorValue value = new ColorValue(ColorMode.HSB, "FON", "FOFF", 10); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "ON".getBytes()); // Normal on state assertThat(value.getChannelState().toString(), is("0,0,10")); @@ -291,8 +291,8 @@ public class ChannelStateTests { @Test public void receiveXYYColorTest() { ColorValue value = new ColorValue(ColorMode.XYY, "FON", "FOFF", 10); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "ON".getBytes()); // Normal on state assertThat(value.getChannelState().toString(), is("0,0,10")); @@ -317,8 +317,8 @@ public class ChannelStateTests { @Test public void receiveLocationTest() { LocationValue value = new LocationValue(); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); c.processMessage("state", "46.833974, 7.108433".getBytes()); assertThat(value.getChannelState().toString(), is("46.833974,7.108433")); @@ -328,8 +328,8 @@ public class ChannelStateTests { @Test public void receiveDateTimeTest() { DateTimeValue value = new DateTimeValue(); - ChannelState subject = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - subject.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState subject = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + subject.start(connectionMock, mock(ScheduledExecutorService.class), 100); ZonedDateTime zd = ZonedDateTime.now(); String datetime = zd.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); @@ -345,10 +345,10 @@ public class ChannelStateTests { @Test public void receiveImageTest() { ImageValue value = new ImageValue(); - ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener)); - c.start(connection, mock(ScheduledExecutorService.class), 100); + ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); + c.start(connectionMock, mock(ScheduledExecutorService.class), 100); - byte[] payload = new byte[] { (byte) 0xFF, (byte) 0xD8, 0x01, 0x02, (byte) 0xFF, (byte) 0xD9 }; + byte[] payload = { (byte) 0xFF, (byte) 0xD8, 0x01, 0x02, (byte) 0xFF, (byte) 0xD9 }; c.processMessage("state", payload); assertThat(value.getChannelState(), is(instanceOf(RawType.class))); assertThat(((RawType) value.getChannelState()).getMimeType(), is("image/jpeg")); diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTransformationTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTransformationTests.java index 0b5676742..8b1af9f86 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTransformationTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTransformationTests.java @@ -20,8 +20,8 @@ import static org.openhab.binding.mqtt.generic.internal.handler.ThingChannelCons import java.util.concurrent.CompletableFuture; -import javax.naming.ConfigurationException; - +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -33,7 +33,6 @@ import org.openhab.binding.mqtt.generic.internal.handler.GenericMQTTThingHandler import org.openhab.binding.mqtt.handler.AbstractBrokerHandler; import org.openhab.core.config.core.Configuration; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; -import org.openhab.core.io.transport.mqtt.MqttException; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; @@ -49,43 +48,44 @@ import org.openhab.core.transform.TransformationService; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class ChannelStateTransformationTests { - private @Mock TransformationService jsonPathService; - private @Mock TransformationServiceProvider transformationServiceProvider; - private @Mock ThingHandlerCallback callback; - private @Mock Thing thing; - private @Mock AbstractBrokerHandler bridgeHandler; - private @Mock MqttBrokerConnection connection; + private @Mock @NonNullByDefault({}) TransformationService jsonPathServiceMock; + private @Mock @NonNullByDefault({}) TransformationServiceProvider transformationServiceProviderMock; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @Mock @NonNullByDefault({}) Thing thingMock; + private @Mock @NonNullByDefault({}) AbstractBrokerHandler bridgeHandlerMock; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; - private GenericMQTTThingHandler thingHandler; + private @NonNullByDefault({}) GenericMQTTThingHandler thingHandler; @BeforeEach - public void setUp() throws ConfigurationException, MqttException { + public void setUp() throws Exception { ThingStatusInfo thingStatus = new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); // Mock the thing: We need the thingUID and the bridgeUID - when(thing.getUID()).thenReturn(testGenericThing); - when(thing.getChannels()).thenReturn(thingChannelListWithJson); - when(thing.getStatusInfo()).thenReturn(thingStatus); - when(thing.getConfiguration()).thenReturn(new Configuration()); + when(thingMock.getUID()).thenReturn(TEST_GENERIC_THING); + when(thingMock.getChannels()).thenReturn(THING_CHANNEL_LIST_WITH_JSON); + when(thingMock.getStatusInfo()).thenReturn(thingStatus); + when(thingMock.getConfiguration()).thenReturn(new Configuration()); // Return the mocked connection object if the bridge handler is asked for it - when(bridgeHandler.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connection)); + when(bridgeHandlerMock.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connectionMock)); - CompletableFuture voidFutureComplete = new CompletableFuture<>(); + CompletableFuture<@Nullable Void> voidFutureComplete = new CompletableFuture<>(); voidFutureComplete.complete(null); - doReturn(voidFutureComplete).when(connection).unsubscribeAll(); - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribe(any(), any()); + doReturn(voidFutureComplete).when(connectionMock).unsubscribeAll(); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribe(any(), any()); - thingHandler = spy(new GenericMQTTThingHandler(thing, mock(MqttChannelStateDescriptionProvider.class), - transformationServiceProvider, 1500)); - when(transformationServiceProvider.getTransformationService(anyString())).thenReturn(jsonPathService); + thingHandler = spy(new GenericMQTTThingHandler(thingMock, mock(MqttChannelStateDescriptionProvider.class), + transformationServiceProviderMock, 1500)); + when(transformationServiceProviderMock.getTransformationService(anyString())).thenReturn(jsonPathServiceMock); - thingHandler.setCallback(callback); + thingHandler.setCallback(callbackMock); // Return the bridge handler if the thing handler asks for it - doReturn(bridgeHandler).when(thingHandler).getBridgeHandler(); + doReturn(bridgeHandlerMock).when(thingHandler).getBridgeHandler(); // We are by default online doReturn(thingStatus).when(thingHandler).getBridgeStatus(); @@ -93,31 +93,31 @@ public class ChannelStateTransformationTests { @SuppressWarnings("null") @Test - public void initialize() throws MqttException { - when(thing.getChannels()).thenReturn(thingChannelListWithJson); + public void initialize() throws Exception { + when(thingMock.getChannels()).thenReturn(THING_CHANNEL_LIST_WITH_JSON); thingHandler.initialize(); - ChannelState channelConfig = thingHandler.getChannelState(textChannelUID); - assertThat(channelConfig.transformationsIn.get(0).pattern, is(jsonPathPattern)); + ChannelState channelConfig = thingHandler.getChannelState(TEXT_CHANNEL_UID); + assertThat(channelConfig.transformationsIn.get(0).pattern, is(JSON_PATH_PATTERN)); } @SuppressWarnings("null") @Test public void processMessageWithJSONPath() throws Exception { - when(jsonPathService.transform(jsonPathPattern, jsonPathJSON)).thenReturn("23.2"); + when(jsonPathServiceMock.transform(JSON_PATH_PATTERN, JSON_PATH_JSON)).thenReturn("23.2"); thingHandler.initialize(); - ChannelState channelConfig = thingHandler.getChannelState(textChannelUID); + ChannelState channelConfig = thingHandler.getChannelState(TEXT_CHANNEL_UID); channelConfig.setChannelStateUpdateListener(thingHandler); ChannelStateTransformation transformation = channelConfig.transformationsIn.get(0); - byte payload[] = jsonPathJSON.getBytes(); - assertThat(transformation.pattern, is(jsonPathPattern)); + byte payload[] = JSON_PATH_JSON.getBytes(); + assertThat(transformation.pattern, is(JSON_PATH_PATTERN)); // Test process message channelConfig.processMessage(channelConfig.getStateTopic(), payload); - verify(callback).stateUpdated(eq(textChannelUID), argThat(arg -> "23.2".equals(arg.toString()))); + verify(callbackMock).stateUpdated(eq(TEXT_CHANNEL_UID), argThat(arg -> "23.2".equals(arg.toString()))); assertThat(channelConfig.getCache().getChannelState().toString(), is("23.2")); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java index 0621138b9..bcfa89e1c 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java @@ -21,6 +21,8 @@ import static org.openhab.binding.mqtt.generic.internal.handler.ThingChannelCons import java.util.concurrent.CompletableFuture; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -57,42 +59,43 @@ import org.openhab.core.types.RefreshType; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class GenericThingHandlerTests { - private @Mock ThingHandlerCallback callback; - private @Mock Thing thing; - private @Mock AbstractBrokerHandler bridgeHandler; - private @Mock MqttBrokerConnection connection; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @Mock @NonNullByDefault({}) Thing thingMock; + private @Mock @NonNullByDefault({}) AbstractBrokerHandler bridgeHandlerMock; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; - private GenericMQTTThingHandler thingHandler; + private @NonNullByDefault({}) GenericMQTTThingHandler thingHandler; @BeforeEach public void setUp() { ThingStatusInfo thingStatus = new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); // Mock the thing: We need the thingUID and the bridgeUID - when(thing.getUID()).thenReturn(testGenericThing); - when(thing.getChannels()).thenReturn(thingChannelList); - when(thing.getStatusInfo()).thenReturn(thingStatus); - when(thing.getConfiguration()).thenReturn(new Configuration()); + when(thingMock.getUID()).thenReturn(TEST_GENERIC_THING); + when(thingMock.getChannels()).thenReturn(THING_CHANNEL_LIST); + when(thingMock.getStatusInfo()).thenReturn(thingStatus); + when(thingMock.getConfiguration()).thenReturn(new Configuration()); // Return the mocked connection object if the bridge handler is asked for it - when(bridgeHandler.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connection)); + when(bridgeHandlerMock.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connectionMock)); - CompletableFuture voidFutureComplete = new CompletableFuture<>(); + CompletableFuture<@Nullable Void> voidFutureComplete = new CompletableFuture<>(); voidFutureComplete.complete(null); - doReturn(voidFutureComplete).when(connection).unsubscribeAll(); - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).publish(any(), any(), anyInt(), + doReturn(voidFutureComplete).when(connectionMock).unsubscribeAll(); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).publish(any(), any(), anyInt(), anyBoolean()); - thingHandler = spy(new GenericMQTTThingHandler(thing, mock(MqttChannelStateDescriptionProvider.class), + thingHandler = spy(new GenericMQTTThingHandler(thingMock, mock(MqttChannelStateDescriptionProvider.class), mock(TransformationServiceProvider.class), 1500)); - thingHandler.setCallback(callback); + thingHandler.setCallback(callbackMock); // Return the bridge handler if the thing handler asks for it - doReturn(bridgeHandler).when(thingHandler).getBridgeHandler(); + doReturn(bridgeHandlerMock).when(thingHandler).getBridgeHandler(); // The broker connection bridge is by default online doReturn(thingStatus).when(thingHandler).getBridgeStatus(); @@ -102,8 +105,8 @@ public class GenericThingHandlerTests { public void initializeWithUnknownThingUID() { ChannelConfig config = textConfiguration().as(ChannelConfig.class); assertThrows(IllegalArgumentException.class, - () -> thingHandler.createChannelState(config, new ChannelUID(testGenericThing, "test"), - ValueFactory.createValueState(config, unknownChannel.getId()))); + () -> thingHandler.createChannelState(config, new ChannelUID(TEST_GENERIC_THING, "test"), + ValueFactory.createValueState(config, UNKNOWN_CHANNEL.getId()))); } @Test @@ -111,16 +114,16 @@ public class GenericThingHandlerTests { thingHandler.initialize(); verify(thingHandler).bridgeStatusChanged(any()); verify(thingHandler).start(any()); - assertThat(thingHandler.getConnection(), is(connection)); + assertThat(thingHandler.getConnection(), is(connectionMock)); - ChannelState channelConfig = thingHandler.channelStateByChannelUID.get(textChannelUID); + ChannelState channelConfig = thingHandler.channelStateByChannelUID.get(TEXT_CHANNEL_UID); assertThat(channelConfig.getStateTopic(), is("test/state")); assertThat(channelConfig.getCommandTopic(), is("test/command")); - verify(connection).subscribe(eq(channelConfig.getStateTopic()), eq(channelConfig)); + verify(connectionMock).subscribe(eq(channelConfig.getStateTopic()), eq(channelConfig)); - verify(callback).statusUpdated(eq(thing), argThat((arg) -> arg.getStatus().equals(ThingStatus.ONLINE) - && arg.getStatusDetail().equals(ThingStatusDetail.NONE))); + verify(callbackMock).statusUpdated(eq(thingMock), argThat(arg -> ThingStatus.ONLINE.equals(arg.getStatus()) + && ThingStatusDetail.NONE.equals(arg.getStatusDetail()))); } @Test @@ -135,24 +138,24 @@ public class GenericThingHandlerTests { doReturn(channelConfig).when(thingHandler).createChannelState(any(), any(), any()); thingHandler.initialize(); - ThingHandlerHelper.setConnection(thingHandler, connection); + ThingHandlerHelper.setConnection(thingHandler, connectionMock); - thingHandler.handleCommand(textChannelUID, RefreshType.REFRESH); - verify(callback).stateUpdated(eq(textChannelUID), argThat(arg -> "DEMOVALUE".equals(arg.toString()))); + thingHandler.handleCommand(TEXT_CHANNEL_UID, RefreshType.REFRESH); + verify(callbackMock).stateUpdated(eq(TEXT_CHANNEL_UID), argThat(arg -> "DEMOVALUE".equals(arg.toString()))); } @Test public void handleCommandUpdateString() { TextValue value = spy(new TextValue()); ChannelState channelConfig = spy( - new ChannelState(ChannelConfigBuilder.create("stateTopic", "commandTopic").build(), textChannelUID, + new ChannelState(ChannelConfigBuilder.create("stateTopic", "commandTopic").build(), TEXT_CHANNEL_UID, value, thingHandler)); doReturn(channelConfig).when(thingHandler).createChannelState(any(), any(), any()); thingHandler.initialize(); - ThingHandlerHelper.setConnection(thingHandler, connection); + ThingHandlerHelper.setConnection(thingHandler, connectionMock); StringType updateValue = new StringType("UPDATE"); - thingHandler.handleCommand(textChannelUID, updateValue); + thingHandler.handleCommand(TEXT_CHANNEL_UID, updateValue); verify(value).update(eq(updateValue)); assertThat(channelConfig.getCache().getChannelState().toString(), is("UPDATE")); } @@ -161,14 +164,14 @@ public class GenericThingHandlerTests { public void handleCommandUpdateBoolean() { OnOffValue value = spy(new OnOffValue("ON", "OFF")); ChannelState channelConfig = spy( - new ChannelState(ChannelConfigBuilder.create("stateTopic", "commandTopic").build(), textChannelUID, + new ChannelState(ChannelConfigBuilder.create("stateTopic", "commandTopic").build(), TEXT_CHANNEL_UID, value, thingHandler)); doReturn(channelConfig).when(thingHandler).createChannelState(any(), any(), any()); thingHandler.initialize(); - ThingHandlerHelper.setConnection(thingHandler, connection); + ThingHandlerHelper.setConnection(thingHandler, connectionMock); StringType updateValue = new StringType("ON"); - thingHandler.handleCommand(textChannelUID, updateValue); + thingHandler.handleCommand(TEXT_CHANNEL_UID, updateValue); verify(value).update(eq(updateValue)); assertThat(channelConfig.getCache().getChannelState(), is(OnOffType.ON)); @@ -178,7 +181,7 @@ public class GenericThingHandlerTests { public void processMessage() { TextValue textValue = new TextValue(); ChannelState channelConfig = spy( - new ChannelState(ChannelConfigBuilder.create("test/state", "test/state/set").build(), textChannelUID, + new ChannelState(ChannelConfigBuilder.create("test/state", "test/state/set").build(), TEXT_CHANNEL_UID, textValue, thingHandler)); doReturn(channelConfig).when(thingHandler).createChannelState(any(), any(), any()); thingHandler.initialize(); @@ -186,10 +189,10 @@ public class GenericThingHandlerTests { // Test process message channelConfig.processMessage("test/state", payload); - verify(callback, atLeastOnce()).statusUpdated(eq(thing), - argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE))); + verify(callbackMock, atLeastOnce()).statusUpdated(eq(thingMock), + argThat(arg -> ThingStatus.ONLINE.equals(arg.getStatus()))); - verify(callback).stateUpdated(eq(textChannelUID), argThat(arg -> "UPDATE".equals(arg.toString()))); + verify(callbackMock).stateUpdated(eq(TEXT_CHANNEL_UID), argThat(arg -> "UPDATE".equals(arg.toString()))); assertThat(textValue.getChannelState().toString(), is("UPDATE")); } @@ -197,11 +200,11 @@ public class GenericThingHandlerTests { public void handleBridgeStatusChange() { Configuration config = new Configuration(); config.put("availabilityTopic", "test/LWT"); - when(thing.getConfiguration()).thenReturn(config); + when(thingMock.getConfiguration()).thenReturn(config); thingHandler.initialize(); thingHandler .bridgeStatusChanged(new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null)); thingHandler.bridgeStatusChanged(new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null)); - verify(connection, times(2)).subscribe(eq("test/LWT"), any()); + verify(connectionMock, times(2)).subscribe(eq("test/LWT"), any()); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java index 69fce0358..00c358a59 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java @@ -37,23 +37,23 @@ import org.openhab.core.thing.type.ChannelTypeUID; @NonNullByDefault public class ThingChannelConstants { // Common ThingUID and ChannelUIDs - public static final ThingUID testGenericThing = new ThingUID(GENERIC_MQTT_THING, "genericthing"); + public static final ThingUID TEST_GENERIC_THING = new ThingUID(GENERIC_MQTT_THING, "genericthing"); - public static final ChannelTypeUID textChannel = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.STRING); - public static final ChannelTypeUID textWithJsonChannel = new ChannelTypeUID(BINDING_ID, + public static final ChannelTypeUID TEXT_CHANNEL = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.STRING); + public static final ChannelTypeUID TEXT_WITH_JSON_CHANNEL = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.STRING); - public static final ChannelTypeUID onoffChannel = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.SWITCH); - public static final ChannelTypeUID numberChannel = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.NUMBER); - public static final ChannelTypeUID percentageChannel = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.DIMMER); - public static final ChannelTypeUID unknownChannel = new ChannelTypeUID(BINDING_ID, "unknown"); + public static final ChannelTypeUID ON_OFF_CHANNEL = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.SWITCH); + public static final ChannelTypeUID NUMBER_CHANNEL = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.NUMBER); + public static final ChannelTypeUID PERCENTAGE_CHANNEL = new ChannelTypeUID(BINDING_ID, MqttBindingConstants.DIMMER); + public static final ChannelTypeUID UNKNOWN_CHANNEL = new ChannelTypeUID(BINDING_ID, "unknown"); - public static final ChannelUID textChannelUID = new ChannelUID(testGenericThing, "mytext"); + public static final ChannelUID TEXT_CHANNEL_UID = new ChannelUID(TEST_GENERIC_THING, "mytext"); - public static final String jsonPathJSON = "{ \"device\": { \"status\": { \"temperature\": 23.2 }}}"; - public static final String jsonPathPattern = "$.device.status.temperature"; + public static final String JSON_PATH_JSON = "{ \"device\": { \"status\": { \"temperature\": 23.2 }}}"; + public static final String JSON_PATH_PATTERN = "$.device.status.temperature"; - public static final List thingChannelList = new ArrayList<>(); - public static final List thingChannelListWithJson = new ArrayList<>(); + public static final List THING_CHANNEL_LIST = new ArrayList<>(); + public static final List THING_CHANNEL_LIST_WITH_JSON = new ArrayList<>(); /** * Create a channel with exact the parameters we need for the tests @@ -65,20 +65,21 @@ public class ThingChannelConstants { * @return */ public static Channel cb(String id, String acceptedType, Configuration config, ChannelTypeUID channelTypeUID) { - return ChannelBuilder.create(new ChannelUID(testGenericThing, id), acceptedType).withConfiguration(config) + return ChannelBuilder.create(new ChannelUID(TEST_GENERIC_THING, id), acceptedType).withConfiguration(config) .withType(channelTypeUID).build(); } static { - thingChannelList.add(cb("mytext", "TextItemType", textConfiguration(), textChannel)); - thingChannelList.add(cb("onoff", "OnOffType", onoffConfiguration(), onoffChannel)); - thingChannelList.add(cb("num", "NumberType", numberConfiguration(), numberChannel)); - thingChannelList.add(cb("percent", "NumberType", percentageConfiguration(), percentageChannel)); + THING_CHANNEL_LIST.add(cb("mytext", "TextItemType", textConfiguration(), TEXT_CHANNEL)); + THING_CHANNEL_LIST.add(cb("onoff", "OnOffType", onoffConfiguration(), ON_OFF_CHANNEL)); + THING_CHANNEL_LIST.add(cb("num", "NumberType", numberConfiguration(), NUMBER_CHANNEL)); + THING_CHANNEL_LIST.add(cb("percent", "NumberType", percentageConfiguration(), PERCENTAGE_CHANNEL)); - thingChannelListWithJson.add(cb("mytext", "TextItemType", textConfigurationWithJson(), textWithJsonChannel)); - thingChannelListWithJson.add(cb("onoff", "OnOffType", onoffConfiguration(), onoffChannel)); - thingChannelListWithJson.add(cb("num", "NumberType", numberConfiguration(), numberChannel)); - thingChannelListWithJson.add(cb("percent", "NumberType", percentageConfiguration(), percentageChannel)); + THING_CHANNEL_LIST_WITH_JSON + .add(cb("mytext", "TextItemType", textConfigurationWithJson(), TEXT_WITH_JSON_CHANNEL)); + THING_CHANNEL_LIST_WITH_JSON.add(cb("onoff", "OnOffType", onoffConfiguration(), ON_OFF_CHANNEL)); + THING_CHANNEL_LIST_WITH_JSON.add(cb("num", "NumberType", numberConfiguration(), NUMBER_CHANNEL)); + THING_CHANNEL_LIST_WITH_JSON.add(cb("percent", "NumberType", percentageConfiguration(), PERCENTAGE_CHANNEL)); } static Configuration textConfiguration() { @@ -92,7 +93,7 @@ public class ThingChannelConstants { Map data = new HashMap<>(); data.put("stateTopic", "test/state"); data.put("commandTopic", "test/command"); - data.put("transformationPattern", "JSONPATH:" + jsonPathPattern); + data.put("transformationPattern", "JSONPATH:" + JSON_PATH_PATTERN); return new Configuration(data); } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/MqttTopicClassMapperTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/MqttTopicClassMapperTests.java index 8b3b51c60..029c8739e 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/MqttTopicClassMapperTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/MqttTopicClassMapperTests.java @@ -29,7 +29,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Stream; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -60,6 +60,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class MqttTopicClassMapperTests { @Retention(RetentionPolicy.RUNTIME) @Target({ FIELD }) @@ -72,15 +73,15 @@ public class MqttTopicClassMapperTests { public transient String ignoreTransient = ""; public final String ignoreFinal = ""; - public @TestValue("string") String aString; - public @TestValue("false") Boolean aBoolean; - public @TestValue("10") Long aLong; - public @TestValue("10") Integer aInteger; - public @TestValue("10") BigDecimal aDecimal; + public @TestValue("string") @Nullable String aString; + public @TestValue("false") @Nullable Boolean aBoolean; + public @TestValue("10") @Nullable Long aLong; + public @TestValue("10") @Nullable Integer aInteger; + public @TestValue("10") @Nullable BigDecimal aDecimal; - public @TestValue("10") @TopicPrefix("a") int Int = 24; + public @TestValue("10") @TopicPrefix("a") int aInt = 24; public @TestValue("false") boolean aBool = true; - public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String[] properties; + public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String @Nullable [] properties; public enum ReadyState { unknown, @@ -99,22 +100,16 @@ public class MqttTopicClassMapperTests { public @TestValue("integer") @MQTTvalueTransform(suffix = "_") DataTypeEnum datatype = DataTypeEnum.unknown; @Override - public @NonNull Object getFieldsOf() { + public Object getFieldsOf() { return this; } } - @Mock - MqttBrokerConnection connection; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; + private @Mock @NonNullByDefault({}) ScheduledExecutorService executorMock; + private @Mock @NonNullByDefault({}) AttributeChanged fieldChangedObserverMock; + private @Spy Object countInjectedFields = new Object(); - @Mock - ScheduledExecutorService executor; - - @Mock - AttributeChanged fieldChangedObserver; - - @Spy - Object countInjectedFields = new Object(); int injectedFields = 0; // A completed future is returned for a subscribe call to the attributes @@ -122,8 +117,8 @@ public class MqttTopicClassMapperTests { @BeforeEach public void setUp() { - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribe(any(), any()); injectedFields = (int) Stream.of(countInjectedFields.getClass().getDeclaredFields()) .filter(AbstractMqttAttributeClass::filterField).count(); } @@ -148,8 +143,8 @@ public class MqttTopicClassMapperTests { anyBoolean()); // Subscribe now to all fields - CompletableFuture future = attributes.subscribeAndReceive(connection, executor, "homie/device123", null, - 10); + CompletableFuture<@Nullable Void> future = attributes.subscribeAndReceive(connectionMock, executorMock, + "homie/device123", null, 10); assertThat(future.isDone(), is(true)); assertThat(attributes.subscriptions.size(), is(10 + injectedFields)); } @@ -157,17 +152,17 @@ public class MqttTopicClassMapperTests { // TODO timeout @SuppressWarnings({ "null", "unused" }) @Test - public void subscribeAndReceive() throws IllegalArgumentException, IllegalAccessException { + public void subscribeAndReceive() throws Exception { final Attributes attributes = spy(new Attributes()); doAnswer(this::createSubscriberAnswer).when(attributes).createSubscriber(any(), any(), anyString(), anyBoolean()); - verify(connection, times(0)).subscribe(anyString(), any()); + verify(connectionMock, times(0)).subscribe(anyString(), any()); // Subscribe now to all fields - CompletableFuture future = attributes.subscribeAndReceive(connection, executor, "homie/device123", - fieldChangedObserver, 10); + CompletableFuture<@Nullable Void> future = attributes.subscribeAndReceive(connectionMock, executorMock, + "homie/device123", fieldChangedObserverMock, 10); assertThat(future.isDone(), is(true)); // We expect 10 subscriptions now @@ -190,7 +185,7 @@ public class MqttTopicClassMapperTests { // Simulate a received MQTT value and use the annotation data as input. f.processMessage(f.topic, annotation.value().getBytes()); - verify(fieldChangedObserver, times(++loopCounter)).attributeChanged(any(), any(), any(), any(), + verify(fieldChangedObserverMock, times(++loopCounter)).attributeChanged(any(), any(), any(), any(), anyBoolean()); // Check each value if the assignment worked @@ -213,23 +208,23 @@ public class MqttTopicClassMapperTests { } @Test - public void ignoresInvalidEnum() throws IllegalArgumentException, IllegalAccessException { + public void ignoresInvalidEnum() throws Exception { final Attributes attributes = spy(new Attributes()); doAnswer(this::createSubscriberAnswer).when(attributes).createSubscriber(any(), any(), anyString(), anyBoolean()); - verify(connection, times(0)).subscribe(anyString(), any()); + verify(connectionMock, times(0)).subscribe(anyString(), any()); // Subscribe now to all fields - CompletableFuture future = attributes.subscribeAndReceive(connection, executor, "homie/device123", - fieldChangedObserver, 10); + CompletableFuture<@Nullable Void> future = attributes.subscribeAndReceive(connectionMock, executorMock, + "homie/device123", fieldChangedObserverMock, 10); assertThat(future.isDone(), is(true)); SubscribeFieldToMQTTtopic field = attributes.subscriptions.stream().filter(f -> f.field.getName() == "state") .findFirst().get(); field.processMessage(field.topic, "garbage".getBytes()); - verify(fieldChangedObserver, times(0)).attributeChanged(any(), any(), any(), any(), anyBoolean()); + verify(fieldChangedObserverMock, times(0)).attributeChanged(any(), any(), any(), any(), anyBoolean()); assertThat(attributes.state.toString(), is("unknown")); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java index baad5b6ef..e2e742bd8 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java @@ -31,7 +31,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -50,6 +50,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class SubscribeFieldToMQTTtopicTests { @Retention(RetentionPolicy.RUNTIME) @Target({ FIELD }) @@ -64,15 +65,15 @@ public class SubscribeFieldToMQTTtopicTests { @SuppressWarnings("unused") public final String ignoreFinal = ""; - public @TestValue("string") String aString; - public @TestValue("false") Boolean aBoolean; - public @TestValue("10") Long aLong; - public @TestValue("10") Integer aInteger; - public @TestValue("10") BigDecimal aDecimal; + public @TestValue("string") @Nullable String aString; + public @TestValue("false") @Nullable Boolean aBoolean; + public @TestValue("10") @Nullable Long aLong; + public @TestValue("10") @Nullable Integer aInteger; + public @TestValue("10") @Nullable BigDecimal aDecimal; - public @TestValue("10") @TopicPrefix("a") int Int = 24; + public @TestValue("10") @TopicPrefix("a") int aInt = 24; public @TestValue("false") boolean aBool = true; - public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String[] properties; + public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String @Nullable [] properties; public enum ReadyState { unknown, @@ -91,53 +92,44 @@ public class SubscribeFieldToMQTTtopicTests { public @TestValue("integer") @MQTTvalueTransform(suffix = "_") DataTypeEnum datatype = DataTypeEnum.unknown; @Override - public @NonNull Object getFieldsOf() { + public Object getFieldsOf() { return this; } } Attributes attributes = new Attributes(); - @Mock - MqttBrokerConnection connection; - - @Mock - SubscribeFieldToMQTTtopic fieldSubscriber; - - @Mock - FieldChanged fieldChanged; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; + private @Mock @NonNullByDefault({}) FieldChanged fieldChangedMock; @BeforeEach public void setUp() { - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); } @Test - public void TimeoutIfNoMessageReceive() - throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException { - final Field field = Attributes.class.getField("Int"); + public void timeoutIfNoMessageReceive() throws Exception { + final Field field = Attributes.class.getField("aInt"); ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); - SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged, + SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChangedMock, "homie/device123", false); assertThrows(TimeoutException.class, - () -> subscriber.subscribeAndReceive(connection, 1000).get(50, TimeUnit.MILLISECONDS)); + () -> subscriber.subscribeAndReceive(connectionMock, 1000).get(50, TimeUnit.MILLISECONDS)); } @Test - public void MandatoryMissing() - throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException { - final Field field = Attributes.class.getField("Int"); + public void mandatoryMissing() throws Exception { + final Field field = Attributes.class.getField("aInt"); ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); - SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged, + SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChangedMock, "homie/device123", true); - assertThrows(ExecutionException.class, () -> subscriber.subscribeAndReceive(connection, 50).get()); + assertThrows(ExecutionException.class, () -> subscriber.subscribeAndReceive(connectionMock, 50).get()); } @Test - public void MessageReceive() - throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException { + public void messageReceive() throws Exception { final FieldChanged changed = (field, value) -> { try { field.set(attributes.getFieldsOf(), value); @@ -145,17 +137,17 @@ public class SubscribeFieldToMQTTtopicTests { fail(e.getMessage()); } }; - final Field field = Attributes.class.getField("Int"); + final Field field = Attributes.class.getField("aInt"); ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, changed, "homie/device123", false); - CompletableFuture<@Nullable Void> future = subscriber.subscribeAndReceive(connection, 1000); + CompletableFuture<@Nullable Void> future = subscriber.subscribeAndReceive(connectionMock, 1000); // Simulate a received MQTT message subscriber.processMessage("ignored", "10".getBytes()); // No timeout should happen future.get(50, TimeUnit.MILLISECONDS); - assertThat(attributes.Int, is(10)); + assertThat(attributes.aInt, is(10)); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java index eb39ed243..8a407c3ad 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java @@ -17,7 +17,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.*; import java.math.BigDecimal; +import java.util.Objects; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.mapping.ColorMode; import org.openhab.core.library.types.DecimalType; @@ -44,9 +46,10 @@ import org.openhab.core.types.TypeParser; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class ValueTests { - Command p(Value v, String str) { - return TypeParser.parseCommand(v.getSupportedCommandTypes(), str); + private Command p(Value v, String str) { + return Objects.requireNonNull(TypeParser.parseCommand(v.getSupportedCommandTypes(), str)); } @Test diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java index b2f40de9c..cb755ac0f 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/ComponentFactory.java @@ -24,8 +24,6 @@ import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChanne import org.openhab.binding.mqtt.homeassistant.internal.exception.ConfigurationException; import org.openhab.binding.mqtt.homeassistant.internal.exception.UnsupportedComponentException; import org.openhab.core.thing.ThingUID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.Gson; @@ -37,8 +35,6 @@ import com.google.gson.Gson; */ @NonNullByDefault public class ComponentFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(ComponentFactory.class); - /** * Create a HA MQTT component. The configuration JSon string is required. * diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/ChannelConfigurationTypeAdapterFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/ChannelConfigurationTypeAdapterFactory.java index 862601a6d..b1418c2d1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/ChannelConfigurationTypeAdapterFactory.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/config/ChannelConfigurationTypeAdapterFactory.java @@ -154,7 +154,7 @@ public class ChannelConfigurationTypeAdapterFactory implements TypeAdapterFactor field.set(config, newValue); } catch (IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); + throw new IllegalStateException(e); } } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/ConfigurationException.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/ConfigurationException.java index cf59a8c1a..111ca895c 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/ConfigurationException.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/ConfigurationException.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.mqtt.homeassistant.internal.exception; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Exception class for errors in HomeAssistant components configurations * * @author Anton Kharuzhy - Initial contribution */ +@NonNullByDefault public class ConfigurationException extends RuntimeException { public ConfigurationException(String message) { super(message); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/UnsupportedComponentException.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/UnsupportedComponentException.java index 3d3941e97..27341e9e7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/UnsupportedComponentException.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/exception/UnsupportedComponentException.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.mqtt.homeassistant.internal.exception; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Exception class for unsupported components * * @author Anton Kharuzhy - Initial contribution */ +@NonNullByDefault public class UnsupportedComponentException extends ConfigurationException { public UnsupportedComponentException(String message) { super(message); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java index d01acd83e..e7dc1a136 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java @@ -19,12 +19,14 @@ import static org.hamcrest.core.IsIterableContaining.hasItem; import java.util.Collection; import java.util.Collections; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.core.config.core.Configuration; /** * @author Jochen Klein - Initial contribution */ +@NonNullByDefault public class HaIDTests { @Test diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java index 1e128ef87..1484868e8 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AbstractComponentTests.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.when; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -33,7 +34,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.mockito.Mock; @@ -56,12 +56,13 @@ import org.openhab.core.types.State; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings({ "ConstantConditions" }) +@NonNullByDefault public abstract class AbstractComponentTests extends AbstractHomeAssistantTests { - private final static int SUBSCRIBE_TIMEOUT = 10000; - private final static int ATTRIBUTE_RECEIVE_TIMEOUT = 2000; + private static final int SUBSCRIBE_TIMEOUT = 10000; + private static final int ATTRIBUTE_RECEIVE_TIMEOUT = 2000; - private @Mock ThingHandlerCallback callback; - private LatchThingHandler thingHandler; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @NonNullByDefault({}) LatchThingHandler thingHandler; @BeforeEach public void setupThingHandler() { @@ -70,12 +71,12 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests config.put(HandlerConfiguration.PROPERTY_BASETOPIC, HandlerConfiguration.DEFAULT_BASETOPIC); config.put(HandlerConfiguration.PROPERTY_TOPICS, getConfigTopics()); - when(callback.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); + when(callbackMock.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); thingHandler = new LatchThingHandler(haThing, channelTypeProvider, transformationServiceProvider, SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); thingHandler.setConnection(bridgeConnection); - thingHandler.setCallback(callback); + thingHandler.setCallback(callbackMock); thingHandler = spy(thingHandler); thingHandler.initialize(); @@ -124,9 +125,7 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests } catch (InterruptedException e) { assertThat(e.getMessage(), false); } - var component = thingHandler.getDiscoveredComponent(); - assertThat(component, CoreMatchers.notNullValue()); - return component; + return Objects.requireNonNull(thingHandler.getDiscoveredComponent()); } /** @@ -141,7 +140,7 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests */ protected static void assertChannel(AbstractComponent<@NonNull ? extends AbstractChannelConfiguration> component, String channelId, String stateTopic, String commandTopic, String label, Class valueClass) { - var stateChannel = component.getChannel(channelId); + var stateChannel = Objects.requireNonNull(component.getChannel(channelId)); assertChannel(stateChannel, stateTopic, commandTopic, label, valueClass); } @@ -236,7 +235,6 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests return false; } - @NonNullByDefault protected static class LatchThingHandler extends HomeAssistantThingHandler { private @Nullable CountDownLatch latch; private @Nullable AbstractComponent<@NonNull ? extends AbstractChannelConfiguration> discoveredComponent; @@ -247,6 +245,7 @@ public abstract class AbstractComponentTests extends AbstractHomeAssistantTests super(thing, channelTypeProvider, transformationServiceProvider, subscribeTimeout, attributeReceiveTimeout); } + @Override public void componentDiscovered(HaID homeAssistantTopicID, AbstractComponent<@NonNull ?> component) { accept(List.of(component)); discoveredComponent = component; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanelTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanelTests.java index 6d6db678a..9e1456267 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanelTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/AlarmControlPanelTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.TextValue; import org.openhab.core.library.types.StringType; @@ -27,6 +28,7 @@ import org.openhab.core.library.types.StringType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class AlarmControlPanelTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "alarm_control_panel/0x0000000000000000_alarm_control_panel_zigbee2mqtt"; @@ -89,6 +91,7 @@ public class AlarmControlPanelTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/alarm/set/state", "ARM_HOME_"); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java index e8a0277a3..fcb544412 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/BinarySensorTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.core.library.types.OnOffType; @@ -27,6 +28,7 @@ import org.openhab.core.types.UnDefType; * * @author Anton Kharuzhy - Initial contribution */ +@NonNullByDefault public class BinarySensorTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "binary_sensor/0x0000000000000000_binary_sensor_zigbee2mqtt"; @@ -148,6 +150,7 @@ public class BinarySensorTests extends AbstractComponentTests { waitForAssert(() -> assertState(component, BinarySensor.SENSOR_CHANNEL_ID, UnDefType.UNDEF), 10000, 200); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CameraTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CameraTests.java index 3cb77eac8..53e2956af 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CameraTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CameraTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.ImageValue; import org.openhab.core.library.types.RawType; @@ -26,6 +27,7 @@ import org.openhab.core.library.types.RawType; * * @author Anton Kharuzhy - Initial contribution */ +@NonNullByDefault public class CameraTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "camera/0x0000000000000000_camera_zigbee2mqtt"; @@ -63,6 +65,7 @@ public class CameraTests extends AbstractComponentTests { assertState(component, Camera.CAMERA_CHANNEL_ID, new RawType(imageBytes, "image/png")); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ClimateTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ClimateTests.java index 9234b0810..1f39a197d 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ClimateTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/ClimateTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.NumberValue; import org.openhab.binding.mqtt.generic.values.OnOffValue; @@ -34,6 +35,7 @@ import org.openhab.core.library.unit.SIUnits; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class ClimateTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "climate/0x847127fffe11dd6a_climate_zigbee2mqtt"; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CoverTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CoverTests.java index 910cb7813..0bfeee34a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CoverTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/CoverTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.RollershutterValue; import org.openhab.core.library.types.PercentType; @@ -28,6 +29,7 @@ import org.openhab.core.library.types.StopMoveType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class CoverTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "cover/0x0000000000000000_cover_zigbee2mqtt"; @@ -82,6 +84,7 @@ public class CoverTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/cover/set/state", "STOP_", 2); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java index 430528358..a0390dad9 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.core.library.types.OnOffType; @@ -27,6 +28,7 @@ import org.openhab.core.library.types.OnOffType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ALL") +@NonNullByDefault public class FanTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "fan/0x0000000000000000_fan_zigbee2mqtt"; @@ -78,6 +80,7 @@ public class FanTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/fan/set/state", "ON_"); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/HAConfigurationTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/HAConfigurationTests.java index 9d3a405d2..ef518cff1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/HAConfigurationTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/HAConfigurationTests.java @@ -19,11 +19,12 @@ import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.UncheckedIOException; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.homeassistant.internal.config.ChannelConfigurationTypeAdapterFactory; import org.openhab.binding.mqtt.homeassistant.internal.config.dto.AbstractChannelConfiguration; @@ -36,6 +37,7 @@ import com.google.gson.GsonBuilder; /** * @author Jochen Klein - Initial contribution */ +@NonNullByDefault public class HAConfigurationTests { private Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ChannelConfigurationTypeAdapterFactory()) @@ -53,7 +55,7 @@ public class HAConfigurationTests { } return result.toString(); } catch (IOException e) { - throw new RuntimeException(e); + throw new UncheckedIOException(e); } } @@ -79,7 +81,7 @@ public class HAConfigurationTests { if (device != null) { assertThat(device.getIdentifiers(), contains("H")); assertThat(device.getConnections(), is(notNullValue())); - List<@NonNull Connection> connections = device.getConnections(); + List connections = device.getConnections(); if (connections != null) { assertThat(connections.get(0).getType(), is("I1")); assertThat(connections.get(0).getIdentifier(), is("I2")); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightTests.java index d21876aa1..219b6c34b 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LightTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.ColorValue; import org.openhab.core.library.types.HSBType; @@ -28,6 +29,7 @@ import org.openhab.core.library.types.OnOffType; * * @author Anton Kharuzhy - Initial contribution */ +@NonNullByDefault public class LightTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "light/0x0000000000000000_light_zigbee2mqtt"; @@ -85,6 +87,7 @@ public class LightTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/light/set/state", "0,0,0"); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LockTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LockTests.java index c0efaae9a..0a8d4de2e 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LockTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/LockTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.core.library.types.OnOffType; @@ -27,6 +28,7 @@ import org.openhab.core.library.types.OnOffType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ALL") +@NonNullByDefault public class LockTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "lock/0x0000000000000000_lock_zigbee2mqtt"; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java index eba2a730c..feffc40f1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.NumberValue; import org.openhab.core.library.types.QuantityType; @@ -29,6 +30,7 @@ import org.openhab.core.types.UnDefType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class SensorTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "sensor/0x0000000000000000_sensor_zigbee2mqtt"; diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java index 40a5a6b67..28738436f 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SwitchTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.core.library.types.OnOffType; @@ -27,6 +28,7 @@ import org.openhab.core.library.types.OnOffType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class SwitchTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt"; @@ -117,6 +119,7 @@ public class SwitchTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/th1/set/auto_lock", "AUTO"); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/VacuumTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/VacuumTests.java index 9ff969e3e..2b0a0f5f2 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/VacuumTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/VacuumTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.binding.mqtt.generic.values.OnOffValue; import org.openhab.binding.mqtt.generic.values.PercentageValue; @@ -32,6 +33,7 @@ import org.openhab.core.types.UnDefType; * @author Anton Kharuzhy - Initial contribution */ @SuppressWarnings("ConstantConditions") +@NonNullByDefault public class VacuumTests extends AbstractComponentTests { public static final String CONFIG_TOPIC = "vacuum/rockrobo_vacuum"; @@ -248,6 +250,7 @@ public class VacuumTests extends AbstractComponentTests { assertPublished("vacuum/send_command", "custom_command"); } + @Override protected Set getConfigTopics() { return Set.of(CONFIG_TOPIC); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java index cfb2a0050..d8614eaa3 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscoveryTests.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mqtt.homeassistant.internal.discovery; -import static org.hamcrest.CoreMatchers.hasItems; -import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import java.util.Collection; @@ -46,8 +45,9 @@ import org.openhab.core.thing.ThingUID; */ @SuppressWarnings({ "ConstantConditions", "unchecked" }) @ExtendWith(MockitoExtension.class) +@NonNullByDefault public class HomeAssistantDiscoveryTests extends AbstractHomeAssistantTests { - private HomeAssistantDiscovery discovery; + private @NonNullByDefault({}) HomeAssistantDiscovery discovery; @BeforeEach public void beforeEach() { @@ -89,11 +89,11 @@ public class HomeAssistantDiscoveryTests extends AbstractHomeAssistantTests { } } - @NonNullByDefault private static class LatchDiscoveryListener implements DiscoveryListener { private final CopyOnWriteArrayList discoveryResults = new CopyOnWriteArrayList<>(); private @Nullable CountDownLatch latch; + @Override public void thingDiscovered(DiscoveryService source, DiscoveryResult result) { discoveryResults.add(result); if (latch != null) { @@ -101,9 +101,11 @@ public class HomeAssistantDiscoveryTests extends AbstractHomeAssistantTests { } } + @Override public void thingRemoved(DiscoveryService source, ThingUID thingUID) { } + @Override public @Nullable Collection removeOlderResults(DiscoveryService source, long timestamp, @Nullable Collection thingTypeUIDs, @Nullable ThingUID bridgeUID) { return Collections.emptyList(); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java index 29f4387d1..4b8516926 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/HomeAssistantThingHandlerTests.java @@ -13,20 +13,15 @@ package org.openhab.binding.mqtt.homeassistant.internal.handler; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +42,7 @@ import org.openhab.core.thing.binding.ThingHandlerCallback; */ @SuppressWarnings({ "ConstantConditions" }) @ExtendWith(MockitoExtension.class) +@NonNullByDefault public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests { private static final int SUBSCRIBE_TIMEOUT = 10000; private static final int ATTRIBUTE_RECEIVE_TIMEOUT = 2000; @@ -62,8 +58,8 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests { private static final List MQTT_TOPICS = CONFIG_TOPICS.stream() .map(AbstractHomeAssistantTests::configTopicToMqtt).collect(Collectors.toList()); - private @Mock ThingHandlerCallback callback; - private HomeAssistantThingHandler thingHandler; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @NonNullByDefault({}) HomeAssistantThingHandler thingHandler; @BeforeEach public void setup() { @@ -72,12 +68,12 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests { config.put(HandlerConfiguration.PROPERTY_BASETOPIC, HandlerConfiguration.DEFAULT_BASETOPIC); config.put(HandlerConfiguration.PROPERTY_TOPICS, CONFIG_TOPICS); - when(callback.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); + when(callbackMock.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing); thingHandler = new HomeAssistantThingHandler(haThing, channelTypeProvider, transformationServiceProvider, SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT); thingHandler.setConnection(bridgeConnection); - thingHandler.setCallback(callback); + thingHandler.setCallback(callbackMock); thingHandler = spy(thingHandler); } @@ -86,7 +82,7 @@ public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests { // When initialize thingHandler.initialize(); - verify(callback).statusUpdated(eq(haThing), any()); + verify(callbackMock).statusUpdated(eq(haThing), any()); // Expect a call to the bridge status changed, the start, the propertiesChanged method verify(thingHandler).bridgeStatusChanged(any()); verify(thingHandler, timeout(SUBSCRIBE_TIMEOUT)).start(any()); diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java index 824087f28..0405bbb1e 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java @@ -13,12 +13,9 @@ package org.openhab.binding.mqtt.homie.generic.internal; 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.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; import org.openhab.binding.mqtt.homie.internal.handler.HomieThingHandler; @@ -45,9 +42,8 @@ import org.osgi.service.component.annotations.Reference; @NonNullByDefault public class MqttThingHandlerFactory extends BaseThingHandlerFactory implements TransformationServiceProvider { private @NonNullByDefault({}) MqttChannelTypeProvider typeProvider; - private @NonNullByDefault({}) MqttChannelStateDescriptionProvider stateDescriptionProvider; - private static final Set SUPPORTED_THING_TYPES_UIDS = Stream - .of(MqttBindingConstants.HOMIE300_MQTT_THING).collect(Collectors.toSet()); + private static final Set SUPPORTED_THING_TYPES_UIDS = Set + .of(MqttBindingConstants.HOMIE300_MQTT_THING); @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -66,15 +62,6 @@ public class MqttThingHandlerFactory extends BaseThingHandlerFactory implements super.deactivate(componentContext); } - @Reference - protected void setStateDescriptionProvider(MqttChannelStateDescriptionProvider stateDescription) { - this.stateDescriptionProvider = stateDescription; - } - - protected void unsetStateDescriptionProvider(MqttChannelStateDescriptionProvider stateDescription) { - this.stateDescriptionProvider = null; - } - @Reference protected void setChannelProvider(MqttChannelTypeProvider provider) { this.typeProvider = provider; diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Device.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Device.java index a2e207907..be4a35cd8 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Device.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Device.java @@ -14,6 +14,7 @@ package org.openhab.binding.mqtt.homie.internal.homie300; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; @@ -275,8 +276,9 @@ public class Device implements AbstractMqttAttributeClass.AttributeChanged { CompletableFuture<@Nullable Void> applyNodes(MqttBrokerConnection connection, ScheduledExecutorService scheduler, int timeout) { - return nodes.apply(attributes.nodes, node -> node.subscribe(connection, scheduler, timeout), this::createNode, - this::notifyNodeRemoved).exceptionally(e -> { + return nodes.apply(Objects.requireNonNull(attributes.nodes), + node -> node.subscribe(connection, scheduler, timeout), this::createNode, this::notifyNodeRemoved) + .exceptionally(e -> { logger.warn("Could not subscribe", e); return null; }); @@ -311,15 +313,11 @@ public class Device implements AbstractMqttAttributeClass.AttributeChanged { * @return Returns a list of relative topics */ public List getRetainedTopics() { - List topics = new ArrayList<>(); + List topics = new ArrayList<>(Stream.of(this.attributes.getClass().getDeclaredFields()) + .map(f -> String.format("%s/$%s", this.deviceID, f.getName())).collect(Collectors.toList())); - topics.addAll(Stream.of(this.attributes.getClass().getDeclaredFields()).map(f -> { - return String.format("%s/$%s", this.deviceID, f.getName()); - }).collect(Collectors.toList())); - - this.nodes.stream().map(n -> n.getRetainedTopics().stream().map(a -> { - return String.format("%s/%s", this.deviceID, a); - }).collect(Collectors.toList())).collect(Collectors.toList()).forEach(topics::addAll); + this.nodes.stream().map(n -> n.getRetainedTopics().stream().map(a -> String.format("%s/%s", this.deviceID, a)) + .collect(Collectors.toList())).collect(Collectors.toList()).forEach(topics::addAll); return topics; } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/DeviceAttributes.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/DeviceAttributes.java index 437964e2a..2cc1144f6 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/DeviceAttributes.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/DeviceAttributes.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.mqtt.homie.internal.homie300; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.mapping.AbstractMqttAttributeClass; import org.openhab.binding.mqtt.generic.mapping.MQTTvalueTransform; import org.openhab.binding.mqtt.generic.mapping.MandatoryField; @@ -24,6 +25,7 @@ import org.openhab.binding.mqtt.generic.mapping.TopicPrefix; * @author David Graeff - Initial contribution */ @TopicPrefix +@NonNullByDefault public class DeviceAttributes extends AbstractMqttAttributeClass { // Lower-case enum value names required. Those are identifiers for the MQTT/homie protocol. public enum ReadyState { @@ -36,13 +38,13 @@ public class DeviceAttributes extends AbstractMqttAttributeClass { alert } - public @MandatoryField String homie; - public @MandatoryField String name; + public @MandatoryField @Nullable String homie; + public @MandatoryField @Nullable String name; public @MandatoryField ReadyState state = ReadyState.unknown; - public @MandatoryField @MQTTvalueTransform(splitCharacter = ",") String[] nodes; + public @MandatoryField @MQTTvalueTransform(splitCharacter = ",") String @Nullable [] nodes; @Override - public @NonNull Object getFieldsOf() { + public Object getFieldsOf() { return this; } } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java index 4d4405a92..7a9e5b055 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Node.java @@ -14,6 +14,7 @@ package org.openhab.binding.mqtt.homie.internal.homie300; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; @@ -173,8 +174,9 @@ public class Node implements AbstractMqttAttributeClass.AttributeChanged { protected CompletableFuture<@Nullable Void> applyProperties(MqttBrokerConnection connection, ScheduledExecutorService scheduler, int timeout) { - return properties.apply(attributes.properties, prop -> prop.subscribe(connection, scheduler, timeout), - this::createProperty, this::notifyPropertyRemoved).exceptionally(e -> { + return properties.apply(Objects.requireNonNull(attributes.properties), + prop -> prop.subscribe(connection, scheduler, timeout), this::createProperty, + this::notifyPropertyRemoved).exceptionally(e -> { logger.warn("Could not subscribe", e); return null; }); @@ -189,10 +191,8 @@ public class Node implements AbstractMqttAttributeClass.AttributeChanged { // Special case: Not all fields were known before if (!attributes.isComplete()) { attributesReceived(connection, scheduler, 500); - } else { - if ("properties".equals(name)) { - applyProperties(connection, scheduler, 500); - } + } else if ("properties".equals(name)) { + applyProperties(connection, scheduler, 500); } callback.nodeAddedOrChanged(this); } @@ -208,15 +208,12 @@ public class Node implements AbstractMqttAttributeClass.AttributeChanged { * @return Returns a list of relative topics */ public List getRetainedTopics() { - List topics = new ArrayList<>(); + List topics = new ArrayList<>(Stream.of(this.attributes.getClass().getDeclaredFields()) + .map(f -> String.format("%s/$%s", this.nodeID, f.getName())).collect(Collectors.toList())); - topics.addAll(Stream.of(this.attributes.getClass().getDeclaredFields()).map(f -> { - return String.format("%s/$%s", this.nodeID, f.getName()); - }).collect(Collectors.toList())); - - this.properties.stream().map(p -> p.getRetainedTopics().stream().map(a -> { - return String.format("%s/%s", this.nodeID, a); - }).collect(Collectors.toList())).collect(Collectors.toList()).forEach(topics::addAll); + this.properties.stream().map(p -> p.getRetainedTopics().stream() + .map(a -> String.format("%s/%s", this.nodeID, a)).collect(Collectors.toList())) + .collect(Collectors.toList()).forEach(topics::addAll); return topics; } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/NodeAttributes.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/NodeAttributes.java index aa22f0dc9..3d3937d9a 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/NodeAttributes.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/NodeAttributes.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.mqtt.homie.internal.homie300; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.mapping.AbstractMqttAttributeClass; import org.openhab.binding.mqtt.generic.mapping.MQTTvalueTransform; import org.openhab.binding.mqtt.generic.mapping.MandatoryField; @@ -24,14 +25,15 @@ import org.openhab.binding.mqtt.generic.mapping.TopicPrefix; * @author David Graeff - Initial contribution */ @TopicPrefix +@NonNullByDefault public class NodeAttributes extends AbstractMqttAttributeClass { - public @MandatoryField String name; - public @MandatoryField @MQTTvalueTransform(splitCharacter = ",") String[] properties; + public @MandatoryField String name = ""; + public @MandatoryField @MQTTvalueTransform(splitCharacter = ",") String @Nullable [] properties; // Type has no meaning yet and is currently purely of textual, descriptive nature - public String type; + public @Nullable String type; @Override - public @NonNull Object getFieldsOf() { + public Object getFieldsOf() { return this; } } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java index ac092abe6..38b14dc3b 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.*; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -40,8 +41,9 @@ import org.openhab.binding.mqtt.homie.internal.homie300.NodeAttributes; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class HomieChildMapTests { - private @Mock DeviceCallback callback; + private @Mock @NonNullByDefault({}) DeviceCallback callbackMock; private final String deviceID = ThingChannelConstants.TEST_HOMIE_THING.getId(); private final String deviceTopic = "homie/" + deviceID; @@ -52,7 +54,7 @@ public class HomieChildMapTests { ChildMap subject = new ChildMap<>(); private Node createNode(String id) { - Node node = new Node(deviceTopic, id, ThingChannelConstants.TEST_HOMIE_THING, callback, + Node node = new Node(deviceTopic, id, ThingChannelConstants.TEST_HOMIE_THING, callbackMock, spy(new NodeAttributes())); doReturn(future).when(node.attributes).subscribeAndReceive(any(), any(), anyString(), any(), anyInt()); doReturn(future).when(node.attributes).unsubscribe(); @@ -60,7 +62,7 @@ public class HomieChildMapTests { } private void removedNode(Node node) { - callback.nodeRemoved(node); + callbackMock.nodeRemoved(node); } public static class AddedAction implements Function> { @@ -85,6 +87,6 @@ public class HomieChildMapTests { Node soonToBeRemoved = subject.get("def"); subject.apply(new String[] { "abc" }, addedAction, this::createNode, this::removedNode); - verify(callback).nodeRemoved(eq(soonToBeRemoved)); + verify(callbackMock).nodeRemoved(eq(soonToBeRemoved)); } } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java index 82a16140b..9dd7e60dc 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/HomieThingHandlerTests.java @@ -30,7 +30,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -82,20 +82,20 @@ import org.openhab.core.types.TypeParser; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class HomieThingHandlerTests { - private Thing thing; + private @Mock @NonNullByDefault({}) AbstractBrokerHandler bridgeHandlerMock; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @Mock @NonNullByDefault({}) MqttBrokerConnection connectionMock; + private @Mock @NonNullByDefault({}) ScheduledExecutorService schedulerMock; + private @Mock @NonNullByDefault({}) ScheduledFuture scheduledFutureMock; + private @Mock @NonNullByDefault({}) ThingTypeRegistry thingTypeRegistryMock; - private @Mock AbstractBrokerHandler bridgeHandler; - private @Mock ThingHandlerCallback callback; - private @Mock MqttBrokerConnection connection; - private @Mock ScheduledExecutorService scheduler; - private @Mock ScheduledFuture scheduledFuture; - private @Mock ThingTypeRegistry thingTypeRegistry; + private @NonNullByDefault({}) Thing thing; + private @NonNullByDefault({}) HomieThingHandler thingHandler; - private HomieThingHandler thingHandler; - - private final MqttChannelTypeProvider channelTypeProvider = new MqttChannelTypeProvider(thingTypeRegistry); + private final MqttChannelTypeProvider channelTypeProvider = new MqttChannelTypeProvider(thingTypeRegistryMock); private final String deviceID = ThingChannelConstants.TEST_HOMIE_THING.getId(); private final String deviceTopic = "homie/" + deviceID; @@ -116,26 +116,27 @@ public class HomieThingHandlerTests { thing.setStatusInfo(thingStatus); // Return the mocked connection object if the bridge handler is asked for it - when(bridgeHandler.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connection)); + when(bridgeHandlerMock.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(connectionMock)); - doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribe(any(), any()); - doReturn(CompletableFuture.completedFuture(true)).when(connection).unsubscribeAll(); - doReturn(CompletableFuture.completedFuture(true)).when(connection).publish(any(), any(), anyInt(), + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).subscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribe(any(), any()); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).unsubscribeAll(); + doReturn(CompletableFuture.completedFuture(true)).when(connectionMock).publish(any(), any(), anyInt(), anyBoolean()); - doReturn(false).when(scheduledFuture).isDone(); - doReturn(scheduledFuture).when(scheduler).schedule(any(Runnable.class), anyLong(), any(TimeUnit.class)); + doReturn(false).when(scheduledFutureMock).isDone(); + doReturn(scheduledFutureMock).when(schedulerMock).schedule(any(Runnable.class), anyLong(), any(TimeUnit.class)); final HomieThingHandler handler = new HomieThingHandler(thing, channelTypeProvider, 1000, 30, 5); thingHandler = spy(handler); - thingHandler.setCallback(callback); + thingHandler.setCallback(callbackMock); final Device device = new Device(thing.getUID(), thingHandler, spy(new DeviceAttributes()), spy(new ChildMap<>())); - thingHandler.setInternalObjects(spy(device), spy(new DelayedBatchProcessing<>(500, thingHandler, scheduler))); + thingHandler.setInternalObjects(spy(device), + spy(new DelayedBatchProcessing<>(500, thingHandler, schedulerMock))); // Return the bridge handler if the thing handler asks for it - doReturn(bridgeHandler).when(thingHandler).getBridgeHandler(); + doReturn(bridgeHandlerMock).when(thingHandler).getBridgeHandler(); // We are by default online doReturn(thingStatus).when(thingHandler).getBridgeStatus(); @@ -153,7 +154,7 @@ public class HomieThingHandlerTests { // Pretend that a device state change arrived. thingHandler.device.attributes.state = ReadyState.ready; - verify(callback, times(0)).statusUpdated(eq(thing), any()); + verify(callbackMock, times(0)).statusUpdated(eq(thing), any()); thingHandler.initialize(); @@ -166,8 +167,8 @@ public class HomieThingHandlerTests { assertThat(thingHandler.device.isInitialized(), is(true)); - verify(callback).statusUpdated(eq(thing), argThat((arg) -> arg.getStatus().equals(ThingStatus.ONLINE) - && arg.getStatusDetail().equals(ThingStatusDetail.NONE))); + verify(callbackMock).statusUpdated(eq(thing), argThat(arg -> ThingStatus.ONLINE.equals(arg.getStatus()) + && ThingStatusDetail.NONE.equals(arg.getStatusDetail()))); } @Test @@ -182,8 +183,8 @@ public class HomieThingHandlerTests { thingHandler.initialize(); - verify(callback).statusUpdated(eq(thing), argThat((arg) -> arg.getStatus().equals(ThingStatus.OFFLINE) - && arg.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); + verify(callbackMock).statusUpdated(eq(thing), argThat(arg -> ThingStatus.OFFLINE.equals(arg.getStatus()) + && ThingStatusDetail.COMMUNICATION_ERROR.equals(arg.getStatusDetail()))); } @Test @@ -199,8 +200,8 @@ public class HomieThingHandlerTests { thingHandler.initialize(); assertThat(thingHandler.device.isInitialized(), is(true)); - verify(callback).statusUpdated(eq(thing), argThat((arg) -> arg.getStatus().equals(ThingStatus.OFFLINE) - && arg.getStatusDetail().equals(ThingStatusDetail.GONE))); + verify(callbackMock).statusUpdated(eq(thing), argThat(arg -> ThingStatus.OFFLINE.equals(arg.getStatus()) + && ThingStatusDetail.GONE.equals(arg.getStatusDetail()))); } @SuppressWarnings("null") @@ -222,12 +223,12 @@ public class HomieThingHandlerTests { node.properties.put(property.propertyID, property); thingHandler.device.nodes.put(node.nodeID, node); - ThingHandlerHelper.setConnection(thingHandler, connection); + ThingHandlerHelper.setConnection(thingHandler, connectionMock); // we need to set a channel value first, undefined values ignored on REFRESH property.getChannelState().getCache().update(new StringType("testString")); thingHandler.handleCommand(property.channelUID, RefreshType.REFRESH); - verify(callback).stateUpdated(argThat(arg -> property.channelUID.equals(arg)), + verify(callbackMock).stateUpdated(argThat(arg -> property.channelUID.equals(arg)), argThat(arg -> property.getChannelState().getCache().getChannelState().equals(arg))); } @@ -252,14 +253,14 @@ public class HomieThingHandlerTests { ChannelState channelState = requireNonNull(property.getChannelState()); assertNotNull(channelState); - ChannelStateHelper.setConnection(channelState, connection);// Pretend we called start() - ThingHandlerHelper.setConnection(thingHandler, connection); + ChannelStateHelper.setConnection(channelState, connectionMock);// Pretend we called start() + ThingHandlerHelper.setConnection(thingHandler, connectionMock); StringType updateValue = new StringType("UPDATE"); thingHandler.handleCommand(property.channelUID, updateValue); assertThat(property.getChannelState().getCache().getChannelState().toString(), is("UPDATE")); - verify(connection, times(1)).publish(any(), any(), anyInt(), anyBoolean()); + verify(connectionMock, times(1)).publish(any(), any(), anyInt(), anyBoolean()); // Check non writable property property.attributes.settable = false; @@ -274,7 +275,7 @@ public class HomieThingHandlerTests { thingHandler.handleCommand(property.channelUID, updateValue); // Expect old value and no MQTT publish assertThat(property.getChannelState().getCache().getChannelState().toString(), is("OLDVALUE")); - verify(connection, times(1)).publish(any(), any(), anyInt(), anyBoolean()); + verify(connectionMock, times(1)).publish(any(), any(), anyInt(), anyBoolean()); } } @@ -320,7 +321,7 @@ public class HomieThingHandlerTests { @Test public void propertiesChanged() throws InterruptedException, ExecutionException { thingHandler.device.initialize("homie", "device", new ArrayList<>()); - ThingHandlerHelper.setConnection(thingHandler, connection); + ThingHandlerHelper.setConnection(thingHandler, connectionMock); // Create mocked homie device tree with one node and one property doAnswer(this::createSubscriberAnswer).when(thingHandler.device.attributes).createSubscriber(any(), any(), @@ -355,14 +356,14 @@ public class HomieThingHandlerTests { thingHandler.delayedProcessing.forceProcessNow(); // Called for the updated property + for the new channels - verify(callback, atLeast(2)).thingUpdated(any()); + verify(callbackMock, atLeast(2)).thingUpdated(any()); - final List<@NonNull Channel> channels = thingHandler.getThing().getChannels(); + final List channels = thingHandler.getThing().getChannels(); assertThat(channels.size(), is(1)); assertThat(channels.get(0).getLabel(), is("testprop")); assertThat(channels.get(0).getKind(), is(ChannelKind.STATE)); - final Map<@NonNull String, @NonNull String> properties = thingHandler.getThing().getProperties(); + final Map properties = thingHandler.getThing().getProperties(); assertThat(properties.get(MqttBindingConstants.HOMIE_PROPERTY_VERSION), is("3.0")); assertThat(properties.size(), is(1)); } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java index 9dd675023..13132a521 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java @@ -12,8 +12,9 @@ */ package org.openhab.binding.mqtt.homie.internal.handler; -import static org.openhab.binding.mqtt.homie.generic.internal.MqttBindingConstants.*; +import static org.openhab.binding.mqtt.homie.generic.internal.MqttBindingConstants.HOMIE300_MQTT_THING; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingUID; /** @@ -21,6 +22,7 @@ import org.openhab.core.thing.ThingUID; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class ThingChannelConstants { public static final ThingUID TEST_HOMIE_THING = new ThingUID(HOMIE300_MQTT_THING, "device123"); } diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java index 129f6cc78..617050e6f 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java @@ -154,13 +154,13 @@ public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallba try { Pin pin; if (config.certificate.isBlank()) { - pin = Pin.LearningPin(PinType.CERTIFICATE_TYPE); + pin = Pin.learningPin(PinType.CERTIFICATE_TYPE); } else { String[] split = config.certificate.split(":"); if (split.length != 2) { throw new NoSuchAlgorithmException("Algorithm is missing"); } - pin = Pin.CheckingPin(PinType.CERTIFICATE_TYPE, new PinMessageDigest(split[0]), + pin = Pin.checkingPin(PinType.CERTIFICATE_TYPE, new PinMessageDigest(split[0]), HexUtils.hexToBytes(split[1])); } trustManager.addPinning(pin); @@ -172,13 +172,13 @@ public class BrokerHandler extends AbstractBrokerHandler implements PinnedCallba try { Pin pin; if (config.publickey.isBlank()) { - pin = Pin.LearningPin(PinType.PUBLIC_KEY_TYPE); + pin = Pin.learningPin(PinType.PUBLIC_KEY_TYPE); } else { String[] split = config.publickey.split(":"); if (split.length != 2) { throw new NoSuchAlgorithmException("Algorithm is missing"); } - pin = Pin.CheckingPin(PinType.PUBLIC_KEY_TYPE, new PinMessageDigest(split[0]), + pin = Pin.checkingPin(PinType.PUBLIC_KEY_TYPE, new PinMessageDigest(split[0]), HexUtils.hexToBytes(split[1])); } trustManager.addPinning(pin); diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java index 8c1f1adff..a3fd005c9 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java @@ -34,8 +34,6 @@ import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; import org.osgi.service.component.annotations.Component; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The {@link MqttBrokerHandlerFactory} is responsible for creating things and thing @@ -52,8 +50,6 @@ public class MqttBrokerHandlerFactory extends BaseThingHandlerFactory implements private static final Set SUPPORTED_THING_TYPES_UIDS = Stream .of(MqttBindingConstants.BRIDGE_TYPE_BROKER).collect(Collectors.toSet()); - private final Logger logger = LoggerFactory.getLogger(MqttBrokerHandlerFactory.class); - /** * This Map provides a lookup between a Topic string (key) and a Set of MQTTTopicDiscoveryParticipants (value), * where the Set itself is a list of participants which are subscribed to the respective Topic. diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttThingID.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttThingID.java index 4069e4c40..c67fa6513 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttThingID.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttThingID.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.mqtt.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.mqtt.MqttBindingConstants; import org.openhab.core.thing.ThingUID; @@ -20,6 +21,7 @@ import org.openhab.core.thing.ThingUID; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class MqttThingID { /** * Convert the url (tcp://122.123.111.123:1883) to a version without colons, dots or slashes diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/Pin.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/Pin.java index 54201776a..6e1c47091 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/Pin.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/Pin.java @@ -72,11 +72,11 @@ public class Pin { this.pinData = data; } - public static Pin LearningPin(PinType pinType) { + public static Pin learningPin(PinType pinType) { return new Pin(pinType, null, true, null); } - public static Pin CheckingPin(PinType pinType, PinMessageDigest method, byte[] pinData) { + public static Pin checkingPin(PinType pinType, PinMessageDigest method, byte[] pinData) { return new Pin(pinType, method, false, pinData); } diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/PinType.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/PinType.java index a14e67067..20801767f 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/PinType.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/ssl/PinType.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.mqtt.internal.ssl; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * A {@link Pin} is either a Public Key or Certificate Pin. * * @author David Graeff - Initial contribution */ +@NonNullByDefault public enum PinType { PUBLIC_KEY_TYPE, CERTIFICATE_TYPE diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java index 13d1a3ff1..2e0afc62a 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java @@ -14,7 +14,7 @@ package org.openhab.binding.mqtt.handler; import static org.mockito.Mockito.verify; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.mockito.Mockito; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.thing.Bridge; @@ -25,6 +25,7 @@ import org.openhab.core.thing.Bridge; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class BrokerHandlerEx extends BrokerHandler { final MqttBrokerConnectionEx e; @@ -34,7 +35,7 @@ public class BrokerHandlerEx extends BrokerHandler { } @Override - protected @NonNull MqttBrokerConnection createBrokerConnection() throws IllegalArgumentException { + protected MqttBrokerConnection createBrokerConnection() throws IllegalArgumentException { return e; } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java index 7414b3a07..16dac9abf 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -48,15 +49,15 @@ import org.osgi.service.cm.ConfigurationException; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class BrokerHandlerTest extends JavaTest { - private ScheduledExecutorService scheduler; - private @Mock ThingHandlerCallback callback; - private @Mock Bridge thing; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @Mock @NonNullByDefault({}) Bridge thingMock; - private MqttBrokerConnectionEx connection; - - private BrokerHandler handler; + private @NonNullByDefault({}) MqttBrokerConnectionEx connection; + private @NonNullByDefault({}) BrokerHandler handler; + private @NonNullByDefault({}) ScheduledExecutorService scheduler; @BeforeEach public void setUp() { @@ -66,10 +67,10 @@ public class BrokerHandlerTest extends JavaTest { connection.setConnectionCallback(connection); Configuration config = new Configuration(); - when(thing.getConfiguration()).thenReturn(config); + when(thingMock.getConfiguration()).thenReturn(config); - handler = spy(new BrokerHandlerEx(thing, connection)); - handler.setCallback(callback); + handler = spy(new BrokerHandlerEx(thingMock, connection)); + handler.setCallback(callbackMock); } @AfterEach @@ -80,7 +81,7 @@ public class BrokerHandlerTest extends JavaTest { @Test public void handlerInitWithoutUrl() throws IllegalArgumentException { // Assume it is a real handler and not a mock as defined above - handler = new BrokerHandler(thing); + handler = new BrokerHandler(thingMock); assertThrows(IllegalArgumentException.class, this::initializeHandlerWaitForTimeout); } @@ -89,7 +90,7 @@ public class BrokerHandlerTest extends JavaTest { Configuration config = new Configuration(); config.put("host", "10.10.0.10"); config.put("port", 80); - when(thing.getConfiguration()).thenReturn(config); + when(thingMock.getConfiguration()).thenReturn(config); handler.initialize(); verify(handler).createBrokerConnection(); } @@ -99,7 +100,7 @@ public class BrokerHandlerTest extends JavaTest { assertThat(initializeHandlerWaitForTimeout(), is(true)); ArgumentCaptor statusInfoCaptor = ArgumentCaptor.forClass(ThingStatusInfo.class); - verify(callback, atLeast(3)).statusUpdated(eq(thing), statusInfoCaptor.capture()); + verify(callbackMock, atLeast(3)).statusUpdated(eq(thingMock), statusInfoCaptor.capture()); assertThat(statusInfoCaptor.getValue().getStatus(), is(ThingStatus.ONLINE)); } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java index fe55d602c..28189ff0a 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java @@ -16,7 +16,6 @@ import static org.mockito.Mockito.spy; import java.util.Map; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; @@ -65,7 +64,7 @@ public class MqttBrokerConnectionEx extends MqttBrokerConnection { } @Override - public @NonNull MqttConnectionState connectionState() { + public MqttConnectionState connectionState() { return connectionStateOverwrite; } } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttConnectionObserverEx.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttConnectionObserverEx.java index 53838b5d9..788e6cb5c 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttConnectionObserverEx.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttConnectionObserverEx.java @@ -14,7 +14,7 @@ package org.openhab.binding.mqtt.handler; import java.util.concurrent.Semaphore; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.io.transport.mqtt.MqttConnectionObserver; import org.openhab.core.io.transport.mqtt.MqttConnectionState; @@ -24,6 +24,7 @@ import org.openhab.core.io.transport.mqtt.MqttConnectionState; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class MqttConnectionObserverEx implements MqttConnectionObserver { public int counter = 0; public Semaphore semaphore = new Semaphore(1); @@ -33,7 +34,7 @@ public class MqttConnectionObserverEx implements MqttConnectionObserver { } @Override - public void connectionStateChanged(@NonNull MqttConnectionState state, @Nullable Throwable error) { + public void connectionStateChanged(MqttConnectionState state, @Nullable Throwable error) { // First we expect a CONNECTING state and then a DISCONNECTED state change if (counter == 0 && state == MqttConnectionState.CONNECTING) { counter = 1; diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java index e41f4dffb..60ec704ec 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.*; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -44,29 +45,23 @@ import org.openhab.core.thing.binding.ThingHandlerCallback; */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) +@NonNullByDefault public class MQTTTopicDiscoveryServiceTest { - private ScheduledExecutorService scheduler; - private MqttBrokerHandlerFactory subject; + private @Mock @NonNullByDefault({}) Bridge thingMock; + private @Mock @NonNullByDefault({}) ThingHandlerCallback callbackMock; + private @Mock @NonNullByDefault({}) MQTTTopicDiscoveryParticipant listenerMock; - @Mock - private Bridge thing; - - @Mock - private ThingHandlerCallback callback; - - @Mock - MQTTTopicDiscoveryParticipant listener; - - private MqttBrokerConnectionEx connection; - - private BrokerHandler handler; + private @NonNullByDefault({}) MqttBrokerConnectionEx connection; + private @NonNullByDefault({}) BrokerHandler handler; + private @NonNullByDefault({}) ScheduledExecutorService scheduler; + private @NonNullByDefault({}) MqttBrokerHandlerFactory subject; @BeforeEach public void setUp() { scheduler = new ScheduledThreadPoolExecutor(1); - when(thing.getUID()).thenReturn(MqttThingID.getThingUID("10.10.0.10", 80)); + when(thingMock.getUID()).thenReturn(MqttThingID.getThingUID("10.10.0.10", 80)); connection = spy(new MqttBrokerConnectionEx("10.10.0.10", 80, false, "BrokerHandlerTest")); connection.setTimeoutExecutor(scheduler, 10); connection.setConnectionCallback(connection); @@ -74,10 +69,10 @@ public class MQTTTopicDiscoveryServiceTest { Configuration config = new Configuration(); config.put("host", "10.10.0.10"); config.put("port", 80); - when(thing.getConfiguration()).thenReturn(config); + when(thingMock.getConfiguration()).thenReturn(config); - handler = spy(new BrokerHandlerEx(thing, connection)); - handler.setCallback(callback); + handler = spy(new BrokerHandlerEx(thingMock, connection)); + handler.setCallback(callbackMock); subject = new MqttBrokerHandlerFactory(); } @@ -92,13 +87,13 @@ public class MQTTTopicDiscoveryServiceTest { handler.initialize(); BrokerHandlerEx.verifyCreateBrokerConnection(handler, 1); - subject.subscribe(listener, "topic"); + subject.subscribe(listenerMock, "topic"); subject.createdHandler(handler); - assertThat(subject.discoveryTopics.get("topic"), hasItem(listener)); + assertThat(subject.discoveryTopics.get("topic"), hasItem(listenerMock)); // Simulate receiving final byte[] bytes = "TEST".getBytes(); connection.getSubscribers().get("topic").messageArrived("topic", bytes, false); - verify(listener).receivedMessage(eq(thing.getUID()), eq(connection), eq("topic"), eq(bytes)); + verify(listenerMock).receivedMessage(eq(thingMock.getUID()), eq(connection), eq("topic"), eq(bytes)); } @Test @@ -107,20 +102,20 @@ public class MQTTTopicDiscoveryServiceTest { BrokerHandlerEx.verifyCreateBrokerConnection(handler, 1); subject.createdHandler(handler); - subject.subscribe(listener, "topic"); - assertThat(subject.discoveryTopics.get("topic"), hasItem(listener)); + subject.subscribe(listenerMock, "topic"); + assertThat(subject.discoveryTopics.get("topic"), hasItem(listenerMock)); // Simulate receiving final byte[] bytes = "TEST".getBytes(); connection.getSubscribers().get("topic").messageArrived("topic", bytes, false); - verify(listener).receivedMessage(eq(thing.getUID()), eq(connection), eq("topic"), eq(bytes)); + verify(listenerMock).receivedMessage(eq(thingMock.getUID()), eq(connection), eq("topic"), eq(bytes)); } @Test public void handlerInitializeAfterSubscribe() { subject.createdHandler(handler); - subject.subscribe(listener, "topic"); - assertThat(subject.discoveryTopics.get("topic"), hasItem(listener)); + subject.subscribe(listenerMock, "topic"); + assertThat(subject.discoveryTopics.get("topic"), hasItem(listenerMock)); // Init handler -> create connection handler.initialize(); @@ -129,7 +124,7 @@ public class MQTTTopicDiscoveryServiceTest { // Simulate receiving final byte[] bytes = "TEST".getBytes(); connection.getSubscribers().get("topic").messageArrived("topic", bytes, false); - verify(listener).receivedMessage(eq(thing.getUID()), eq(connection), eq("topic"), eq(bytes)); + verify(listenerMock).receivedMessage(eq(thingMock.getUID()), eq(connection), eq("topic"), eq(bytes)); } @Test @@ -138,12 +133,12 @@ public class MQTTTopicDiscoveryServiceTest { BrokerHandlerEx.verifyCreateBrokerConnection(handler, 1); subject.createdHandler(handler); - subject.subscribe(listener, "topic"); - assertThat(subject.discoveryTopics.get("topic"), hasItem(listener)); + subject.subscribe(listenerMock, "topic"); + assertThat(subject.discoveryTopics.get("topic"), hasItem(listenerMock)); // Simulate receiving final byte[] bytes = "".getBytes(); connection.getSubscribers().get("topic").messageArrived("topic", bytes, false); - verify(listener).topicVanished(eq(thing.getUID()), eq(connection), eq("topic")); + verify(listenerMock).topicVanished(eq(thingMock.getUID()), eq(connection), eq("topic")); } } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/ssl/PinningSSLContextProviderTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/ssl/PinningSSLContextProviderTest.java index 31f697119..789417be3 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/ssl/PinningSSLContextProviderTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/ssl/PinningSSLContextProviderTest.java @@ -25,7 +25,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.openhab.core.util.HexUtils; @@ -34,6 +34,7 @@ import org.openhab.core.util.HexUtils; * * @author David Graeff - Initial contribution */ +@NonNullByDefault public class PinningSSLContextProviderTest { @Test @@ -61,7 +62,7 @@ public class PinningSSLContextProviderTest { @Test public void certPinCallsX509CertificateGetEncoded() throws NoSuchAlgorithmException, CertificateException { PinTrustManager pinTrustManager = new PinTrustManager(); - pinTrustManager.addPinning(Pin.LearningPin(PinType.CERTIFICATE_TYPE)); + pinTrustManager.addPinning(Pin.learningPin(PinType.CERTIFICATE_TYPE)); // Mock a certificate X509Certificate certificate = mock(X509Certificate.class); @@ -77,7 +78,7 @@ public class PinningSSLContextProviderTest { @Test public void pubKeyPinCallsX509CertificateGetPublicKey() throws NoSuchAlgorithmException, CertificateException { PinTrustManager pinTrustManager = new PinTrustManager(); - pinTrustManager.addPinning(Pin.LearningPin(PinType.PUBLIC_KEY_TYPE)); + pinTrustManager.addPinning(Pin.learningPin(PinType.PUBLIC_KEY_TYPE)); // Mock a certificate PublicKey publicKey = mock(PublicKey.class); @@ -102,8 +103,7 @@ public class PinningSSLContextProviderTest { } @Override - @NonNull - PinMessageDigest getMessageDigestForSigAlg(@NonNull String sigAlg) throws CertificateException { + PinMessageDigest getMessageDigestForSigAlg(String sigAlg) throws CertificateException { return pinMessageDigest; } } @@ -116,7 +116,7 @@ public class PinningSSLContextProviderTest { byte[] digestOfTestCert = pinMessageDigest.digest(testCert); // Add a certificate pin in learning mode to a trust manager - Pin pin = Pin.LearningPin(PinType.CERTIFICATE_TYPE); + Pin pin = Pin.learningPin(PinType.CERTIFICATE_TYPE); pinTrustManager.addPinning(pin); assertThat(pinTrustManager.pins.size(), is(1)); @@ -150,7 +150,7 @@ public class PinningSSLContextProviderTest { byte[] digestOfTestCert = pinMessageDigest.digest(testCert); // Add a certificate pin in checking mode to a trust manager - Pin pin = Pin.CheckingPin(PinType.CERTIFICATE_TYPE, pinMessageDigest, digestOfTestCert); + Pin pin = Pin.checkingPin(PinType.CERTIFICATE_TYPE, pinMessageDigest, digestOfTestCert); pinTrustManager.addPinning(pin); assertThat(pinTrustManager.pins.size(), is(1));