mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[fmiweather] Fix compiler warnings and SAT issues (#17621)
* Reduce number of warnings and SAT issues Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
c9351b3dcb
commit
2c7c1c586f
@ -18,6 +18,7 @@ import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -81,13 +82,11 @@ public abstract class AbstractWeatherHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PMD.CompareObjectsWithEquals")
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (RefreshType.REFRESH == command) {
|
||||
ScheduledFuture<?> prevFuture = updateChannelsFutureRef.get();
|
||||
ScheduledFuture<?> newFuture = updateChannelsFutureRef
|
||||
.updateAndGet(fut -> fut == null || fut.isDone() ? submitUpdateChannelsThrottled() : fut);
|
||||
assert newFuture != null; // invariant
|
||||
ScheduledFuture<?> newFuture = Objects.requireNonNull(updateChannelsFutureRef
|
||||
.updateAndGet(fut -> fut == null || fut.isDone() ? submitUpdateChannelsThrottled() : fut));
|
||||
if (logger.isTraceEnabled()) {
|
||||
long delayRemainingMillis = newFuture.getDelay(TimeUnit.MILLISECONDS);
|
||||
if (delayRemainingMillis <= 0) {
|
||||
@ -97,7 +96,7 @@ public abstract class AbstractWeatherHandler extends BaseThingHandler {
|
||||
delayRemainingMillis);
|
||||
}
|
||||
// Compare by reference to check if the future changed
|
||||
if (prevFuture == newFuture) {
|
||||
if (isSameFuture(prevFuture, newFuture)) {
|
||||
logger.trace("REFRESH received. Previous refresh ongoing, will wait for it to complete in {} ms",
|
||||
lastRefreshMillis + REFRESH_THROTTLE_MILLIS - System.currentTimeMillis());
|
||||
}
|
||||
@ -105,6 +104,11 @@ public abstract class AbstractWeatherHandler extends BaseThingHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.CompareObjectsWithEquals")
|
||||
private boolean isSameFuture(@Nullable ScheduledFuture<?> future1, @Nullable ScheduledFuture<?> future2) {
|
||||
return future1 == future2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
client = new Client();
|
||||
|
@ -232,7 +232,6 @@ public class ForecastWeatherHandler extends AbstractWeatherHandler {
|
||||
return (int) (TimeUnit.HOURS.toMinutes(hours) / QUERY_RESOLUTION_MINUTES);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unused", "null" })
|
||||
private static @Nullable String getDataField(ChannelUID channelUID) {
|
||||
Entry<String, @Nullable Unit<?>> entry = CHANNEL_TO_FORECAST_FIELD_NAME_AND_UNIT
|
||||
.get(channelUID.getIdWithoutGroup());
|
||||
@ -242,7 +241,6 @@ public class ForecastWeatherHandler extends AbstractWeatherHandler {
|
||||
return entry.getKey();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unused", "null" })
|
||||
private static @Nullable Unit<?> getUnit(ChannelUID channelUID) {
|
||||
Entry<String, @Nullable Unit<?>> entry = CHANNEL_TO_FORECAST_FIELD_NAME_AND_UNIT
|
||||
.get(channelUID.getIdWithoutGroup());
|
||||
|
@ -62,10 +62,17 @@ public class ObservationWeatherHandler extends AbstractWeatherHandler {
|
||||
private static final long OBSERVATION_LOOK_BACK_SECONDS = TimeUnit.MINUTES.toSeconds(30);
|
||||
private static final int STEP_MINUTES = 10;
|
||||
private static final int POLL_INTERVAL_SECONDS = 600;
|
||||
private static BigDecimal HUNDRED = BigDecimal.valueOf(100);
|
||||
private static BigDecimal NA_CLOUD_MAX = BigDecimal.valueOf(8); // API value when having full clouds (overcast)
|
||||
private static BigDecimal NA_CLOUD_COVERAGE = BigDecimal.valueOf(9); // API value when cloud coverage could not be
|
||||
// determined.
|
||||
private static final BigDecimal HUNDRED = BigDecimal.valueOf(100);
|
||||
|
||||
/**
|
||||
* API value when having full clouds (overcast)
|
||||
*/
|
||||
private static final BigDecimal NA_CLOUD_MAX = BigDecimal.valueOf(8);
|
||||
|
||||
/**
|
||||
* API value when cloud coverage could not be determined.
|
||||
*/
|
||||
private static final BigDecimal NA_CLOUD_COVERAGE = BigDecimal.valueOf(9);
|
||||
|
||||
public static final Unit<Length> MILLIMETRE = MetricPrefix.MILLI(METRE);
|
||||
public static final Unit<Length> CENTIMETRE = MetricPrefix.CENTI(METRE);
|
||||
@ -175,7 +182,6 @@ public class ObservationWeatherHandler extends AbstractWeatherHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "null", "unused" })
|
||||
private static @Nullable String getDataField(ChannelUID channelUID) {
|
||||
Entry<String, @Nullable Unit<?>> entry = CHANNEL_TO_OBSERVATION_FIELD_NAME_AND_UNIT
|
||||
.get(channelUID.getIdWithoutGroup());
|
||||
@ -185,7 +191,6 @@ public class ObservationWeatherHandler extends AbstractWeatherHandler {
|
||||
return entry.getKey();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "null", "unused" })
|
||||
private static @Nullable Unit<?> getUnit(ChannelUID channelUID) {
|
||||
Entry<String, @Nullable Unit<?>> entry = CHANNEL_TO_OBSERVATION_FIELD_NAME_AND_UNIT
|
||||
.get(channelUID.getIdWithoutGroup());
|
||||
|
@ -15,7 +15,6 @@ package org.openhab.binding.fmiweather.internal.client;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@ -67,22 +66,20 @@ import org.xml.sax.SAXException;
|
||||
@NonNullByDefault
|
||||
public class Client {
|
||||
|
||||
private static final String WEATHER_STATIONS_URL = "https://opendata.fmi.fi/wfs/fin?service=WFS&version=2.0.0&request=GetFeature&storedquery_id=fmi::ef::stations&networkid=121&";
|
||||
|
||||
private static final Map<String, String> NAMESPACES = Map.of( //
|
||||
"target", "http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.1", //
|
||||
"gml", "http://www.opengis.net/gml/3.2", //
|
||||
"xlink", "http://www.w3.org/1999/xlink", //
|
||||
"ows", "http://www.opengis.net/ows/1.1", //
|
||||
"gmlcov", "http://www.opengis.net/gmlcov/1.0", //
|
||||
"swe", "http://www.opengis.net/swe/2.0", //
|
||||
"wfs", "http://www.opengis.net/wfs/2.0", //
|
||||
"ef", "http://inspire.ec.europa.eu/schemas/ef/4.0");
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Client.class);
|
||||
|
||||
public static final String WEATHER_STATIONS_URL = "https://opendata.fmi.fi/wfs/fin?service=WFS&version=2.0.0&request=GetFeature&storedquery_id=fmi::ef::stations&networkid=121&";
|
||||
|
||||
private static final Map<String, String> NAMESPACES = new HashMap<>();
|
||||
static {
|
||||
NAMESPACES.put("target", "http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.1");
|
||||
NAMESPACES.put("gml", "http://www.opengis.net/gml/3.2");
|
||||
NAMESPACES.put("xlink", "http://www.w3.org/1999/xlink");
|
||||
NAMESPACES.put("ows", "http://www.opengis.net/ows/1.1");
|
||||
NAMESPACES.put("gmlcov", "http://www.opengis.net/gmlcov/1.0");
|
||||
NAMESPACES.put("swe", "http://www.opengis.net/swe/2.0");
|
||||
|
||||
NAMESPACES.put("wfs", "http://www.opengis.net/wfs/2.0");
|
||||
NAMESPACES.put("ef", "http://inspire.ec.europa.eu/schemas/ef/4.0");
|
||||
}
|
||||
private static final NamespaceContext NAMESPACE_CONTEXT = new NamespaceContext() {
|
||||
@Override
|
||||
public @Nullable String getNamespaceURI(@Nullable String prefix) {
|
||||
@ -91,12 +88,12 @@ public class Client {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public @Nullable Iterator getPrefixes(@Nullable String val) {
|
||||
public @Nullable Iterator getPrefixes(@Nullable String namespaceURI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getPrefix(@Nullable String uri) {
|
||||
public @Nullable String getPrefix(@Nullable String namespaceURI) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@ -173,7 +170,7 @@ public class Client {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Location> parseStations(String response) throws FMIExceptionReportException,
|
||||
protected Set<Location> parseStations(String response) throws FMIExceptionReportException,
|
||||
FMIUnexpectedResponseException, SAXException, IOException, XPathExpressionException {
|
||||
Document document = documentBuilder.parse(new InputSource(new StringReader(response)));
|
||||
|
||||
@ -218,7 +215,7 @@ public class Client {
|
||||
* Parse FMI multipointcoverage formatted xml response
|
||||
*
|
||||
*/
|
||||
private FMIResponse parseMultiPointCoverageXml(String response) throws FMIUnexpectedResponseException,
|
||||
protected FMIResponse parseMultiPointCoverageXml(String response) throws FMIUnexpectedResponseException,
|
||||
FMIExceptionReportException, SAXException, IOException, XPathExpressionException {
|
||||
Document document = documentBuilder.parse(new InputSource(new StringReader(response)));
|
||||
|
||||
|
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@ -54,11 +55,15 @@ public class FMIResponse {
|
||||
|
||||
public Builder appendLocationData(Location location, @Nullable Integer capacityHintForValues, String parameter,
|
||||
long epochSecond, @Nullable BigDecimal val) {
|
||||
timestampsByLocationByParameter.computeIfAbsent(location, k -> new HashMap<>()).computeIfAbsent(parameter,
|
||||
k -> capacityHintForValues == null ? new ArrayList<>() : new ArrayList<>(capacityHintForValues))
|
||||
Objects.requireNonNull(Objects
|
||||
.requireNonNull(timestampsByLocationByParameter.computeIfAbsent(location, k -> new HashMap<>()))
|
||||
.computeIfAbsent(parameter, k -> capacityHintForValues == null ? new ArrayList<>()
|
||||
: new ArrayList<>(capacityHintForValues)))
|
||||
.add(epochSecond);
|
||||
valuesByLocationByParameter.computeIfAbsent(location, k -> new HashMap<>()).computeIfAbsent(parameter,
|
||||
k -> capacityHintForValues == null ? new ArrayList<>() : new ArrayList<>(capacityHintForValues))
|
||||
Objects.requireNonNull(
|
||||
Objects.requireNonNull(valuesByLocationByParameter.computeIfAbsent(location, k -> new HashMap<>()))
|
||||
.computeIfAbsent(parameter, k -> capacityHintForValues == null ? new ArrayList<>()
|
||||
: new ArrayList<>(capacityHintForValues)))
|
||||
.add(val);
|
||||
return this;
|
||||
}
|
||||
@ -85,10 +90,11 @@ public class FMIResponse {
|
||||
Entry<String, List<Long>> parameterEntry) {
|
||||
String parameter = parameterEntry.getKey();
|
||||
long[] timestamps = parameterEntry.getValue().stream().mapToLong(Long::longValue).toArray();
|
||||
BigDecimal[] values = valuesByLocationByParameter.get(location).get(parameter)
|
||||
BigDecimal[] values = Objects
|
||||
.requireNonNull(Objects.requireNonNull(valuesByLocationByParameter.get(location)).get(parameter))
|
||||
.toArray(new @Nullable BigDecimal[0]);
|
||||
Data dataValues = new Data(timestamps, values);
|
||||
out.get(location).put(parameter, dataValues);
|
||||
Objects.requireNonNull(out.get(location)).put(parameter, dataValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,8 @@ public class Request {
|
||||
public final String storedQueryId;
|
||||
public final String[] parameters;
|
||||
|
||||
private static ZoneId UTC = ZoneId.of("Z");
|
||||
private static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
private static final ZoneId UTC = ZoneId.of("Z");
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
|
||||
public Request(String storedQueryId, QueryParameter location, long startEpoch, long endEpoch,
|
||||
long timestepMinutes) {
|
||||
|
@ -10,23 +10,16 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URISyntaxException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.hamcrest.Description;
|
||||
@ -37,6 +30,9 @@ import org.openhab.binding.fmiweather.internal.client.Client;
|
||||
import org.openhab.binding.fmiweather.internal.client.Data;
|
||||
import org.openhab.binding.fmiweather.internal.client.FMIResponse;
|
||||
import org.openhab.binding.fmiweather.internal.client.Location;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIExceptionReportException;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIUnexpectedResponseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Base class for response parsing tests
|
||||
@ -47,41 +43,23 @@ import org.openhab.binding.fmiweather.internal.client.Location;
|
||||
public class AbstractFMIResponseParsingTest {
|
||||
|
||||
@NonNullByDefault({})
|
||||
protected Client client;
|
||||
protected ClientExposed client;
|
||||
|
||||
@BeforeEach
|
||||
public void setUpClient() {
|
||||
client = new Client();
|
||||
client = new ClientExposed();
|
||||
}
|
||||
|
||||
protected Path getTestResource(String filename) {
|
||||
try {
|
||||
return Paths.get(getClass().getResource(filename).toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
fail(e.getMessage());
|
||||
// Make the compiler happy by throwing here, fails already above
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
protected String readTestResourceUtf8(String filename) {
|
||||
return readTestResourceUtf8(getTestResource(filename));
|
||||
}
|
||||
|
||||
protected String readTestResourceUtf8(Path path) {
|
||||
try {
|
||||
BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
|
||||
StringBuilder content = new StringBuilder();
|
||||
char[] buffer = new char[1024];
|
||||
int read = -1;
|
||||
while ((read = reader.read(buffer)) != -1) {
|
||||
content.append(buffer, 0, read);
|
||||
protected String readTestResourceUtf8(String filename) throws IOException {
|
||||
try (InputStream inputStream = AbstractFMIResponseParsingTest.class.getResourceAsStream(filename)) {
|
||||
if (inputStream == null) {
|
||||
throw new IOException("Input stream is null");
|
||||
}
|
||||
return content.toString();
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
// Make the compiler happy by throwing here, fails already above
|
||||
throw new IllegalStateException();
|
||||
byte[] bytes = inputStream.readAllBytes();
|
||||
if (bytes == null) {
|
||||
throw new IOException("Resulting byte-array empty");
|
||||
}
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,42 +121,15 @@ public class AbstractFMIResponseParsingTest {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
* @throws Throwable exception raised by parseMultiPointCoverageXml
|
||||
* @throws AssertionError exception raised when parseMultiPointCoverageXml method signature does not match excepted
|
||||
* (test & implementation is out-of-sync)
|
||||
*/
|
||||
protected FMIResponse parseMultiPointCoverageXml(String content) throws Throwable {
|
||||
try {
|
||||
Method parseMethod = Client.class.getDeclaredMethod("parseMultiPointCoverageXml", String.class);
|
||||
parseMethod.setAccessible(true);
|
||||
return Objects.requireNonNull((FMIResponse) parseMethod.invoke(client, content));
|
||||
} catch (InvocationTargetException e) {
|
||||
throw e.getTargetException();
|
||||
} catch (Exception e) {
|
||||
fail(String.format("Unexpected reflection error (code changed?) %s: %s", e.getClass().getName(),
|
||||
e.getMessage()));
|
||||
// Make the compiler happy by throwing here, fails already above
|
||||
throw new IllegalStateException();
|
||||
protected class ClientExposed extends Client {
|
||||
public FMIResponse parseMultiPointCoverageXml(String response) throws FMIUnexpectedResponseException,
|
||||
FMIExceptionReportException, SAXException, IOException, XPathExpressionException {
|
||||
return super.parseMultiPointCoverageXml(response);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Set<Location> parseStations(String content) {
|
||||
try {
|
||||
Method parseMethod = Objects.requireNonNull(Client.class.getDeclaredMethod("parseStations", String.class));
|
||||
parseMethod.setAccessible(true);
|
||||
return Objects.requireNonNull((Set<Location>) parseMethod.invoke(client, content));
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e.getTargetException());
|
||||
} catch (Exception e) {
|
||||
fail(String.format("Unexpected reflection error (code changed?) %s: %s", e.getClass().getName(),
|
||||
e.getMessage()));
|
||||
// Make the compiler happy by throwing here, fails already above
|
||||
throw new IllegalStateException();
|
||||
public Set<Location> parseStations(String response) throws FMIExceptionReportException,
|
||||
FMIUnexpectedResponseException, SAXException, IOException, XPathExpressionException {
|
||||
return super.parseStations(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,12 +10,10 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -24,7 +22,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.openhab.binding.fmiweather.internal.AbstractWeatherHandler;
|
||||
import org.openhab.binding.fmiweather.internal.client.Data;
|
||||
|
||||
/**
|
||||
@ -41,33 +38,15 @@ public class AbstractWeatherHandlerTest {
|
||||
}
|
||||
|
||||
protected static long floorToEvenMinutes(long epochSeconds, int roundMinutes) {
|
||||
final Method method;
|
||||
try {
|
||||
method = AbstractWeatherHandler.class.getDeclaredMethod("floorToEvenMinutes", long.class, int.class);
|
||||
method.setAccessible(true);
|
||||
Object res = method.invoke("", epochSeconds, roundMinutes);
|
||||
assertNotNull(res);
|
||||
return (long) res;
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
fail(e);
|
||||
throw new IllegalStateException(); // to make compiler happy
|
||||
}
|
||||
Object res = AbstractWeatherHandler.floorToEvenMinutes(epochSeconds, roundMinutes);
|
||||
assertNotNull(res);
|
||||
return (long) res;
|
||||
}
|
||||
|
||||
protected static long ceilToEvenMinutes(long epochSeconds, int roundMinutes) {
|
||||
final Method method;
|
||||
try {
|
||||
method = AbstractWeatherHandler.class.getDeclaredMethod("ceilToEvenMinutes", long.class, int.class);
|
||||
method.setAccessible(true);
|
||||
Object res = method.invoke("", epochSeconds, roundMinutes);
|
||||
assertNotNull(res);
|
||||
return (long) res;
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
fail(e);
|
||||
throw new IllegalStateException(); // to make compiler happy
|
||||
}
|
||||
Object res = AbstractWeatherHandler.ceilToEvenMinutes(epochSeconds, roundMinutes);
|
||||
assertNotNull(res);
|
||||
return (long) res;
|
||||
}
|
||||
|
||||
public static List<Object[]> parametersForFloorToEvenMinutes() {
|
||||
@ -81,18 +60,9 @@ public class AbstractWeatherHandlerTest {
|
||||
}
|
||||
|
||||
protected static int lastValidIndex(Data data) {
|
||||
final Method method;
|
||||
try {
|
||||
method = AbstractWeatherHandler.class.getDeclaredMethod("lastValidIndex", Data.class);
|
||||
method.setAccessible(true);
|
||||
Object res = method.invoke("", data);
|
||||
assertNotNull(res);
|
||||
return (int) res;
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
fail(e);
|
||||
throw new IllegalStateException(); // to make compiler happy
|
||||
}
|
||||
Object res = AbstractWeatherHandler.lastValidIndex(data);
|
||||
assertNotNull(res);
|
||||
return (int) res;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
@ -10,43 +10,48 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.Client;
|
||||
import org.openhab.binding.fmiweather.internal.client.FMIResponse;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIExceptionReportException;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIUnexpectedResponseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Test cases for {@link Client.parseMultiPointCoverageXml} with an "empty" (no data) XML response
|
||||
* Test cases for {@link org.openhab.binding.fmiweather.internal.client.Client#parseMultiPointCoverageXml}
|
||||
* with an "empty" (no data) XML response
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FMIResponseParsingEmptyTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path observations = getTestResource("observations_empty.xml");
|
||||
private static final String OBSERVATIONS = "observations_empty.xml";
|
||||
|
||||
@NonNullByDefault({})
|
||||
private FMIResponse observationsResponse;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
client = new Client();
|
||||
try {
|
||||
observationsResponse = parseMultiPointCoverageXml(readTestResourceUtf8(observations));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Test data malformed", e);
|
||||
}
|
||||
public void setUp() throws FMIUnexpectedResponseException, FMIExceptionReportException, XPathExpressionException,
|
||||
SAXException, IOException {
|
||||
client = new ClientExposed();
|
||||
observationsResponse = client.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS));
|
||||
assertNotNull(observationsResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationsSinglePlace() throws Throwable {
|
||||
public void testLocationsSinglePlace() {
|
||||
assertThat(observationsResponse.getLocations().size(), is(0));
|
||||
}
|
||||
}
|
@ -10,38 +10,37 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIResponseException;
|
||||
|
||||
/**
|
||||
* Test cases for AbstractWeatherHandler. The tests provide mocks for supporting entities using Mockito.
|
||||
* Test cases for {@link AbstractWeatherHandler}.
|
||||
* The tests provide mocks for supporting entities using Mockito.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FMIResponseParsingExceptionReportTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path error1 = getTestResource("error1.xml");
|
||||
private static final String ERROR1 = "error1.xml";
|
||||
|
||||
@Test
|
||||
public void testErrorResponse() {
|
||||
try {
|
||||
parseMultiPointCoverageXml(readTestResourceUtf8(error1));
|
||||
client.parseMultiPointCoverageXml(readTestResourceUtf8(ERROR1));
|
||||
} catch (FMIResponseException e) {
|
||||
// OK
|
||||
assertThat(e.getMessage(), is(
|
||||
"Exception report (OperationParsingFailed): [Invalid time interval!, The start time is later than the end time., URI: /wfs?endtime=1900-03-10T20%3A10%3A00Z&fmisid=101023¶meters=t2m%2Crh%2Cwd_10min%2Cws_10min%2Cwg_10min%2Cp_sea&request=getFeature&service=WFS&starttime=2019-03-10T10%3A10%3A00Z&storedquery_id=fmi%3A%3Aobservations%3A%3Aweather%3A%3Amultipointcoverage×tep=60&version=2.0.0]"));
|
||||
return;
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
fail("Wrong exception, was " + e.getClass().getName());
|
||||
}
|
||||
fail("FMIResponseException expected");
|
@ -10,36 +10,35 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIResponseException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Test cases for AbstractWeatherHandler. The tests provide mocks for supporting entities using Mockito.
|
||||
* Test cases for {@link AbstractWeatherHandler}.
|
||||
* The tests provide mocks for supporting entities using Mockito.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FMIResponseParsingInvalidOrUnexpectedXmlTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path observations1 = getTestResource("observations_single_place.xml");
|
||||
private static final String OBSERVATIONS1 = "observations_single_place.xml";
|
||||
|
||||
@Test
|
||||
public void testInvalidXml() {
|
||||
assertThrows(SAXParseException.class,
|
||||
() -> parseMultiPointCoverageXml(readTestResourceUtf8(observations1).replace("276.0", "<<")));
|
||||
() -> client.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS1).replace("276.0", "<<")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnexpectedXml() {
|
||||
assertThrows(FMIResponseException.class,
|
||||
() -> parseMultiPointCoverageXml(readTestResourceUtf8(observations1).replace("276.0", "<foo>4</foo>")));
|
||||
assertThrows(FMIResponseException.class, () -> client
|
||||
.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS1).replace("276.0", "<foo>4</foo>")));
|
||||
}
|
||||
}
|
@ -10,34 +10,39 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.Data;
|
||||
import org.openhab.binding.fmiweather.internal.client.FMIResponse;
|
||||
import org.openhab.binding.fmiweather.internal.client.Location;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIExceptionReportException;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIUnexpectedResponseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Test cases for Client.parseMultiPointCoverageXml with a xml response having multiple places, parameters
|
||||
* and timestamps
|
||||
* Test cases for {@link org.openhab.binding.fmiweather.internal.client.Client#parseMultiPointCoverageXml}
|
||||
* with a xml response having multiple places, parameters and timestamps
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FMIResponseParsingMultiplePlacesTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path observationsMultiplePlaces = getTestResource("observations_multiple_places.xml");
|
||||
private Path forecastsMultiplePlaces = getTestResource("forecast_multiple_places.xml");
|
||||
private static final String OBSERVATIONS_MULTIPLE_PLACES = "observations_multiple_places.xml";
|
||||
private static final String FORECAST_MULTIPLE_PLACES = "forecast_multiple_places.xml";
|
||||
|
||||
@NonNullByDefault({})
|
||||
private FMIResponse observationsMultiplePlacesResponse;
|
||||
@ -61,16 +66,14 @@ public class FMIResponseParsingMultiplePlacesTest extends AbstractFMIResponsePar
|
||||
new BigDecimal("19.90000"));
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
try {
|
||||
observationsMultiplePlacesResponse = parseMultiPointCoverageXml(
|
||||
readTestResourceUtf8(observationsMultiplePlaces));
|
||||
observationsMultiplePlacesNaNResponse = parseMultiPointCoverageXml(
|
||||
readTestResourceUtf8(observationsMultiplePlaces).replace("276.0", "NaN"));
|
||||
forecastsMultiplePlacesResponse = parseMultiPointCoverageXml(readTestResourceUtf8(forecastsMultiplePlaces));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Test data malformed", e);
|
||||
}
|
||||
public void setUp() throws FMIUnexpectedResponseException, FMIExceptionReportException, XPathExpressionException,
|
||||
SAXException, IOException {
|
||||
observationsMultiplePlacesResponse = client
|
||||
.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS_MULTIPLE_PLACES));
|
||||
observationsMultiplePlacesNaNResponse = client
|
||||
.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS_MULTIPLE_PLACES).replace("276.0", "NaN"));
|
||||
forecastsMultiplePlacesResponse = client
|
||||
.parseMultiPointCoverageXml(readTestResourceUtf8(FORECAST_MULTIPLE_PLACES));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -111,8 +114,8 @@ public class FMIResponseParsingMultiplePlacesTest extends AbstractFMIResponsePar
|
||||
|
||||
@Test
|
||||
public void testParseObservationsMultipleData() {
|
||||
Data wd_10min = observationsMultiplePlacesResponse.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd_10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
Data wd10min = observationsMultiplePlacesResponse.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
"243.0", "252.0", "262.0", "276.0")));
|
||||
Data rh = observationsMultiplePlacesResponse.getData(kilpilahti, "rh").get();
|
||||
assertThat(rh, is(deeplyEqualTo(1552215600L, 60, "73.0", "65.0", "60.0", "59.0", "57.0", "64.0", "66.0", "65.0",
|
||||
@ -140,8 +143,8 @@ public class FMIResponseParsingMultiplePlacesTest extends AbstractFMIResponsePar
|
||||
@Test
|
||||
public void testParseObservations1NaN() {
|
||||
// last value is null, due to NaN measurement value
|
||||
Data wd_10min = observationsMultiplePlacesNaNResponse.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd_10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
Data wd10min = observationsMultiplePlacesNaNResponse.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
"243.0", "252.0", "262.0", null)));
|
||||
}
|
||||
}
|
@ -10,35 +10,39 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.Data;
|
||||
import org.openhab.binding.fmiweather.internal.client.FMIResponse;
|
||||
import org.openhab.binding.fmiweather.internal.client.Location;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIExceptionReportException;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIUnexpectedResponseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Test cases for Client.parseMultiPointCoverageXml with a xml response having single place and multiple
|
||||
* parameters
|
||||
* and timestamps
|
||||
* Test cases for {@link {@link org.openhab.binding.fmiweather.internal.client.Client#parseMultiPointCoverageXml}
|
||||
* with an xml response having single place and multiple parameters and timestamps
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FMIResponseParsingSinglePlaceTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path observations1 = getTestResource("observations_single_place.xml");
|
||||
private static final String OBSERVATIONS1 = "observations_single_place.xml";
|
||||
|
||||
@NonNullByDefault({})
|
||||
private FMIResponse observationsResponse1;
|
||||
@ -48,14 +52,11 @@ public class FMIResponseParsingSinglePlaceTest extends AbstractFMIResponseParsin
|
||||
new BigDecimal("25.62546"));
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
try {
|
||||
observationsResponse1 = parseMultiPointCoverageXml(readTestResourceUtf8(observations1));
|
||||
observationsResponse1NaN = parseMultiPointCoverageXml(
|
||||
readTestResourceUtf8(observations1).replace("276.0", "NaN"));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Test data malformed", e);
|
||||
}
|
||||
public void setUp() throws FMIUnexpectedResponseException, FMIExceptionReportException, XPathExpressionException,
|
||||
SAXException, IOException {
|
||||
observationsResponse1 = client.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS1));
|
||||
observationsResponse1NaN = client
|
||||
.parseMultiPointCoverageXml(readTestResourceUtf8(OBSERVATIONS1).replace("276.0", "NaN"));
|
||||
assertNotNull(observationsResponse1);
|
||||
}
|
||||
|
||||
@ -86,16 +87,16 @@ public class FMIResponseParsingSinglePlaceTest extends AbstractFMIResponseParsin
|
||||
|
||||
@Test
|
||||
public void testParseObservations1Data() {
|
||||
Data wd_10min = observationsResponse1.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd_10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
Data wd10min = observationsResponse1.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
"243.0", "252.0", "262.0", "276.0")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseObservations1NaN() {
|
||||
// last value is null, due to NaN measurement value
|
||||
Data wd_10min = observationsResponse1NaN.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd_10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
Data wd10min = observationsResponse1NaN.getData(emasalo, "wd_10min").get();
|
||||
assertThat(wd10min, is(deeplyEqualTo(1552215600L, 60, "312.0", "286.0", "295.0", "282.0", "271.0", "262.0",
|
||||
"243.0", "252.0", "262.0", null)));
|
||||
}
|
||||
}
|
@ -10,34 +10,39 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.fmiweather.internal.client.Location;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIExceptionReportException;
|
||||
import org.openhab.binding.fmiweather.internal.client.exception.FMIUnexpectedResponseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Test cases for Client.parseStations
|
||||
* Test cases for {@link org.openhab.binding.fmiweather.internal.client.Client#parseStations}
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ParsingStationsTest extends AbstractFMIResponseParsingTest {
|
||||
|
||||
private Path stations_xml = getTestResource("stations.xml");
|
||||
private static final String STATIONS_XML = "stations.xml";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testParseStations() {
|
||||
Set<Location> stations = parseStations(readTestResourceUtf8(stations_xml));
|
||||
public void testParseStations() throws FMIExceptionReportException, FMIUnexpectedResponseException, SAXException,
|
||||
IOException, XPathExpressionException {
|
||||
Set<Location> stations = client.parseStations(readTestResourceUtf8(STATIONS_XML));
|
||||
assertNotNull(stations);
|
||||
assertThat(stations.size(), is(3));
|
||||
assertThat(stations,
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.fmiweather;
|
||||
package org.openhab.binding.fmiweather.internal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
@ -40,7 +40,6 @@ public class ValuesMatcher extends TypeSafeMatcher<@Nullable BigDecimal[]> {
|
||||
return s == null ? null : new BigDecimal(s);
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
@Override
|
||||
public void describeTo(@Nullable Description description) {
|
||||
if (description == null) {
|
Loading…
Reference in New Issue
Block a user