diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java index 7a12c3e586682..581b0752052f0 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java @@ -32,7 +32,6 @@ import org.openhab.binding.astro.internal.handler.AstroThingHandler; import org.openhab.binding.astro.internal.handler.MoonHandler; import org.openhab.binding.astro.internal.handler.SunHandler; -import org.openhab.binding.astro.internal.util.PropertyUtils; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -51,12 +50,13 @@ public class AstroHandlerFactory extends BaseThingHandlerFactory { .collect(Collectors.toSet()); private static final Map ASTRO_THING_HANDLERS = new HashMap<>(); private final CronScheduler scheduler; + private final TimeZoneProvider timeZoneProvider; @Activate public AstroHandlerFactory(final @Reference CronScheduler scheduler, final @Reference TimeZoneProvider timeZoneProvider) { this.scheduler = scheduler; - PropertyUtils.setTimeZoneProvider(timeZoneProvider); + this.timeZoneProvider = timeZoneProvider; } @Override @@ -69,9 +69,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); AstroThingHandler thingHandler = null; if (thingTypeUID.equals(THING_TYPE_SUN)) { - thingHandler = new SunHandler(thing, scheduler); + thingHandler = new SunHandler(thing, scheduler, timeZoneProvider); } else if (thingTypeUID.equals(THING_TYPE_MOON)) { - thingHandler = new MoonHandler(thing, scheduler); + thingHandler = new MoonHandler(thing, scheduler, timeZoneProvider); } if (thingHandler != null) { ASTRO_THING_HANDLERS.put(thing.getUID().toString(), thingHandler); diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java index 375aa046115d7..fc8eb7492d204 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java @@ -32,6 +32,7 @@ import org.apache.commons.lang.time.DateFormatUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.scheduler.ScheduledCompletableFuture; import org.eclipse.smarthome.core.thing.Channel; @@ -66,6 +67,8 @@ public abstract class AstroThingHandler extends BaseThingHandler { /** Scheduler to schedule jobs */ private final CronScheduler cronScheduler; + private final TimeZoneProvider timeZoneProvider; + private final Lock monitor = new ReentrantLock(); private final Set> scheduledFutures = new HashSet<>(); @@ -76,9 +79,10 @@ public abstract class AstroThingHandler extends BaseThingHandler { private @Nullable ScheduledCompletableFuture dailyJob; - public AstroThingHandler(Thing thing, CronScheduler scheduler) { + public AstroThingHandler(Thing thing, final CronScheduler scheduler, final TimeZoneProvider timeZoneProvider) { super(thing); this.cronScheduler = scheduler; + this.timeZoneProvider = timeZoneProvider; } @Override @@ -155,7 +159,8 @@ public void publishPlanet() { * Publishes the channel with data if it's linked. */ public void publishChannelIfLinked(ChannelUID channelUID) { - if (isLinked(channelUID.getId()) && getPlanet() != null) { + Planet planet = getPlanet(); + if (isLinked(channelUID.getId()) && planet != null) { final Channel channel = getThing().getChannel(channelUID.getId()); if (channel == null) { logger.error("Cannot find channel for {}", channelUID); @@ -163,7 +168,8 @@ public void publishChannelIfLinked(ChannelUID channelUID) { } try { AstroChannelConfig config = channel.getConfiguration().as(AstroChannelConfig.class); - updateState(channelUID, PropertyUtils.getState(channelUID, config, getPlanet())); + updateState(channelUID, + PropertyUtils.getState(channelUID, config, planet, timeZoneProvider.getTimeZone())); } catch (Exception ex) { logger.error("Can't update state for channel {} : {}", channelUID, ex.getMessage(), ex); } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java index 7b3df13ac3a1d..737bfbd0475ae 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -49,8 +50,8 @@ public class MoonHandler extends AstroThingHandler { /** * Constructor */ - public MoonHandler(Thing thing, CronScheduler scheduler) { - super(thing, scheduler); + public MoonHandler(Thing thing, final CronScheduler scheduler, final TimeZoneProvider timeZoneProvider) { + super(thing, scheduler, timeZoneProvider); } @Override diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java index 9add11e6c1b26..ccab3cabee083 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -49,8 +50,8 @@ public class SunHandler extends AstroThingHandler { /** * Constructor */ - public SunHandler(Thing thing, CronScheduler scheduler) { - super(thing, scheduler); + public SunHandler(Thing thing, final CronScheduler scheduler, final TimeZoneProvider timeZoneProvider) { + super(thing, scheduler, timeZoneProvider); } @Override diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/util/PropertyUtils.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/util/PropertyUtils.java index d357663d856e0..bdbc3c4c766d4 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/util/PropertyUtils.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/util/PropertyUtils.java @@ -15,13 +15,15 @@ import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; import org.apache.commons.lang.StringUtils; -import org.eclipse.smarthome.core.i18n.TimeZoneProvider; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DateTimeType; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.StringType; @@ -37,6 +39,7 @@ * @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType * @author Christoph Weitkamp - Introduced UoM */ +@NonNullByDefault public class PropertyUtils { /** Constructor */ @@ -44,12 +47,11 @@ private PropertyUtils() { throw new IllegalAccessError("Non-instantiable"); } - private static TimeZoneProvider timeZoneProvider; - /** * Returns the state of the channel. */ - public static State getState(ChannelUID channelUID, AstroChannelConfig config, Object instance) throws Exception { + public static State getState(ChannelUID channelUID, AstroChannelConfig config, Object instance, ZoneId zoneId) + throws Exception { Object value = getPropertyValue(channelUID, instance); if (value == null) { return UnDefType.UNDEF; @@ -58,7 +60,7 @@ public static State getState(ChannelUID channelUID, AstroChannelConfig config, O } else if (value instanceof Calendar) { Calendar cal = (Calendar) value; GregorianCalendar gregorianCal = (GregorianCalendar) DateTimeUtils.applyConfig(cal, config); - cal.setTimeZone(TimeZone.getTimeZone(timeZoneProvider.getTimeZone())); + cal.setTimeZone(TimeZone.getTimeZone(zoneId)); ZonedDateTime zoned = gregorianCal.toZonedDateTime().withFixedOffsetZone(); return new DateTimeType(zoned); } else if (value instanceof Number) { @@ -71,15 +73,11 @@ public static State getState(ChannelUID channelUID, AstroChannelConfig config, O } } - public static void setTimeZoneProvider(TimeZoneProvider timeZoneProvider) { - PropertyUtils.timeZoneProvider = timeZoneProvider; - } - /** * Returns the property value from the object instance, nested properties are possible. If the propertyName is for * example rise.start, the methods getRise().getStart() are called. */ - public static Object getPropertyValue(ChannelUID channelUID, Object instance) throws Exception { + public static @Nullable Object getPropertyValue(ChannelUID channelUID, Object instance) throws Exception { String[] properties = StringUtils.split(channelUID.getId(), "#"); return getPropertyValue(instance, properties, 0); } @@ -88,7 +86,8 @@ public static Object getPropertyValue(ChannelUID channelUID, Object instance) th * Iterates through the nested properties and returns the getter value. */ @SuppressWarnings("all") - private static Object getPropertyValue(Object instance, String[] properties, int nestedIndex) throws Exception { + private static @Nullable Object getPropertyValue(Object instance, String[] properties, int nestedIndex) + throws Exception { String propertyName = properties[nestedIndex]; Method m = instance.getClass().getMethod(toGetterString(propertyName), null); Object result = m.invoke(instance, (Object[]) null); diff --git a/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/model/SunTest.java b/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/model/SunTest.java index bf77b1aaa3027..c96e6c940ad7c 100644 --- a/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/model/SunTest.java +++ b/bundles/org.openhab.binding.astro/src/test/java/org/openhab/binding/astro/internal/model/SunTest.java @@ -12,16 +12,16 @@ */ package org.openhab.binding.astro.internal.model; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; + +import java.time.ZoneId; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.types.UnDefType; import org.junit.Before; import org.junit.Test; +import org.openhab.binding.astro.internal.config.AstroChannelConfig; import org.openhab.binding.astro.internal.util.PropertyUtils; /*** @@ -35,23 +35,29 @@ public class SunTest { private Sun sun; + private AstroChannelConfig config; + + private static ZoneId ZONE = ZoneId.systemDefault(); @Before public void init() { sun = new Sun(); + config = new AstroChannelConfig(); } @Test public void testConstructor() throws Exception { assertNotNull(sun.getPhase()); - assertEquals(UnDefType.UNDEF, PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), null, sun)); + assertEquals(UnDefType.UNDEF, + PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), config, sun, ZONE)); } @Test public void testGetStateWhenNullPhaseName() throws Exception { sun.getPhase().setName(null); - assertEquals(UnDefType.UNDEF, PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), null, sun)); + assertEquals(UnDefType.UNDEF, + PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), config, sun, ZONE)); } @Test @@ -59,7 +65,7 @@ public void testGetStateWhenNotNullPhaseName() throws Exception { sun.getPhase().setName(SunPhaseName.DAYLIGHT); assertEquals(new StringType("DAYLIGHT"), - PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), null, sun)); + PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), config, sun, ZONE)); } @Test(expected = NullPointerException.class) @@ -67,7 +73,8 @@ public void testGetStateWhenNullPhase() throws Exception { sun.setPhase(null); assertNull(sun.getPhase()); - assertEquals(UnDefType.UNDEF, PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), null, sun)); + assertEquals(UnDefType.UNDEF, + PropertyUtils.getState(new ChannelUID("astro:sun:home:phase#name"), config, sun, ZONE)); } @Test diff --git a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroCommandTest.java b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroCommandTest.java index 9303e374d3648..cdf4a7b3f3fe9 100644 --- a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroCommandTest.java +++ b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroCommandTest.java @@ -17,7 +17,10 @@ import static org.openhab.binding.astro.internal.AstroBindingConstants.THING_TYPE_SUN; import static org.openhab.binding.astro.test.cases.AstroBindingTestsData.*; +import java.time.ZoneId; + import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -60,7 +63,9 @@ public void testRefreshCommandUpdatesTheStateOfTheChannels() { ThingHandlerCallback callback = mock(ThingHandlerCallback.class); CronScheduler cronScheduler = mock(CronScheduler.class); - AstroThingHandler sunHandler = spy(new SunHandler(thing, cronScheduler)); + TimeZoneProvider timeZoneProvider = mock(TimeZoneProvider.class); + when(timeZoneProvider.getTimeZone()).thenReturn(ZoneId.systemDefault()); + AstroThingHandler sunHandler = spy(new SunHandler(thing, cronScheduler, timeZoneProvider)); // Required from the AstroThingHandler to send the status update doReturn(true).when(callback).isChannelLinked(eq(channelUID)); diff --git a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroValidConfigurationTest.java b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroValidConfigurationTest.java index 93a6e48431391..6cb6e437778ed 100644 --- a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroValidConfigurationTest.java +++ b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/handler/test/AstroValidConfigurationTest.java @@ -16,7 +16,10 @@ import static org.openhab.binding.astro.internal.AstroBindingConstants.THING_TYPE_SUN; import static org.openhab.binding.astro.test.cases.AstroBindingTestsData.*; +import java.time.ZoneId; + import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; @@ -143,7 +146,9 @@ private void assertThingStatus(Configuration configuration, ThingStatus expected ThingHandlerCallback callback = mock(ThingHandlerCallback.class); CronScheduler cronScheduler = mock(CronScheduler.class); - ThingHandler sunHandler = new SunHandler(thing, cronScheduler); + TimeZoneProvider timeZoneProvider = mock(TimeZoneProvider.class); + when(timeZoneProvider.getTimeZone()).thenReturn(ZoneId.systemDefault()); + ThingHandler sunHandler = new SunHandler(thing, cronScheduler, timeZoneProvider); sunHandler.setCallback(callback); sunHandler.initialize(); diff --git a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/test/AstroStateTest.java b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/test/AstroStateTest.java index 99750aeb38316..ec2a567d893a0 100644 --- a/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/test/AstroStateTest.java +++ b/itests/org.openhab.binding.astro.tests/src/main/java/org/openhab/binding/astro/test/AstroStateTest.java @@ -24,7 +24,6 @@ import java.util.GregorianCalendar; import java.util.List; -import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.types.State; @@ -72,13 +71,6 @@ public static List data() { @Test public void testParametrized() { - // Anonymous implementation of the service to adapt the time zone to the tested longitude and latitude - PropertyUtils.setTimeZoneProvider(new TimeZoneProvider() { - @Override - public ZoneId getTimeZone() { - return ZONE_ID; - } - }); try { assertStateUpdate(thingID, channelId, expectedState); } catch (Exception e) { @@ -88,7 +80,7 @@ public ZoneId getTimeZone() { private void assertStateUpdate(String thingID, String channelId, State expectedState) throws Exception { ChannelUID testItemChannelUID = new ChannelUID(getThingUID(thingID), channelId); - State state = PropertyUtils.getState(testItemChannelUID, new AstroChannelConfig(), getPlanet(thingID)); + State state = PropertyUtils.getState(testItemChannelUID, new AstroChannelConfig(), getPlanet(thingID), ZONE_ID); assertEquals(expectedState, state); }