Skip to content

Commit

Permalink
Extend support to ISO8601 format for sitemap chart period parameter
Browse files Browse the repository at this point in the history
Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo committed Nov 18, 2023
1 parent 26283da commit fe68de7
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
*/
package org.openhab.core.ui.internal.chart;

import static java.util.Map.entry;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
Expand Down Expand Up @@ -69,6 +68,7 @@
*
* @author Chris Jackson - Initial contribution
* @author Holger Reichert - Support for themes, DPI, legend hiding
* @author Laurent Garnier - Extend support to ISO8601 format for chart period parameter
*/
@Component(immediate = true, service = { ChartServlet.class, Servlet.class }, configurationPid = "org.openhab.chart", //
property = Constants.SERVICE_PID + "=org.openhab.chart")
Expand Down Expand Up @@ -99,17 +99,7 @@ public class ChartServlet extends HttpServlet {
// The URI of this servlet
public static final String SERVLET_PATH = "/chart";

private static final Duration DEFAULT_PERIOD = Duration.ofDays(1);

private static final Map<String, Duration> PERIODS = Map.ofEntries( //
entry("h", Duration.ofHours(1)), entry("4h", Duration.ofHours(4)), //
entry("8h", Duration.ofHours(8)), entry("12h", Duration.ofHours(12)), //
entry("D", Duration.ofDays(1)), entry("2D", Duration.ofDays(2)), //
entry("3D", Duration.ofDays(3)), entry("W", Duration.ofDays(7)), //
entry("2W", Duration.ofDays(14)), entry("M", Duration.ofDays(30)), //
entry("2M", Duration.ofDays(60)), entry("4M", Duration.ofDays(120)), //
entry("Y", Duration.ofDays(365))//
);
private static final Duration DEFAULT_DURATION = Duration.ofDays(1);

protected static final Map<String, ChartProvider> CHART_PROVIDERS = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -233,7 +223,8 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser
}

// Read out the parameter period, begin and end and save them.
Duration period = periodParam == null ? DEFAULT_PERIOD : PERIODS.getOrDefault(periodParam, DEFAULT_PERIOD);
Period period = convertToPeriod(periodParam, Period.ZERO);
Duration duration = convertToDuration(periodParam, DEFAULT_DURATION);
ZonedDateTime timeBegin = null;
ZonedDateTime timeEnd = null;

Expand All @@ -260,13 +251,13 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser
// Set begin and end time and check legality.
if (timeBegin == null && timeEnd == null) {
timeEnd = ZonedDateTime.now(timeZoneProvider.getTimeZone());
timeBegin = timeEnd.minus(period);
timeBegin = timeEnd.minus(!period.isZero() ? period : duration);
logger.debug("No begin or end is specified, use now as end and now-period as begin.");
} else if (timeEnd == null) {
timeEnd = timeBegin.plus(period);
timeEnd = timeBegin.plus(!period.isZero() ? period : duration);
logger.debug("No end is specified, use begin + period as end.");
} else if (timeBegin == null) {
timeBegin = timeEnd.minus(period);
timeBegin = timeEnd.minus(!period.isZero() ? period : duration);
logger.debug("No begin is specified, use end-period as begin");
} else if (timeEnd.isBefore(timeBegin)) {
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "The end is before the begin.");
Expand Down Expand Up @@ -359,4 +350,42 @@ public void init(@Nullable ServletConfig config) throws ServletException {
@Override
public void destroy() {
}

public static Period convertToPeriod(@Nullable String periodParam, Period defaultPeriod) {
Period period = defaultPeriod;
String convertedPeriod = convertPeriodToISO8601(periodParam);
if (convertedPeriod != null) {
try {
period = Period.parse(convertedPeriod);
} catch (DateTimeParseException e) {
// Ignored
}
}
return period;
}

public static Duration convertToDuration(@Nullable String periodParam, Duration defaultDuration) {
Duration duration = defaultDuration;
String convertedPeriod = convertPeriodToISO8601(periodParam);
if (convertedPeriod != null) {
try {
duration = Duration.parse(convertedPeriod);
} catch (DateTimeParseException e) {
// Ignored
}
}
return duration;
}

private static @Nullable String convertPeriodToISO8601(@Nullable String period) {
if (period == null || period.startsWith("P") || !(period.endsWith("h") || period.endsWith("D")
|| period.endsWith("W") || period.endsWith("M") || period.endsWith("Y"))) {
return period;
}
String newPeriod = period.length() == 1 ? "1" + period : period;
if (newPeriod.endsWith("h")) {
newPeriod = "T" + newPeriod.replace("h", "H");
}
return "P" + newPeriod;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.ui.internal.chart;

import static org.junit.jupiter.api.Assertions.*;

import java.time.Duration;
import java.time.Period;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;

/**
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class ChartServletPeriodParamTest {

@Test
public void convertToPeriodFromNull() {
Period period = ChartServlet.convertToPeriod(null, Period.ZERO);
assertTrue(period.isZero());
}

@Test
public void convertToPeriodFromHours() {
Period period = ChartServlet.convertToPeriod("2h", Period.ZERO);
assertTrue(period.isZero());
}

@Test
public void convertToPeriodFromDays() {
Period period = ChartServlet.convertToPeriod("D", Period.ZERO);
assertEquals(1, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(0, period.getYears());

period = ChartServlet.convertToPeriod("4D", Period.ZERO);
assertEquals(4, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(0, period.getYears());
}

@Test
public void convertToPeriodFromWeeks() {
Period period = ChartServlet.convertToPeriod("W", Period.ZERO);
assertEquals(7, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(0, period.getYears());

period = ChartServlet.convertToPeriod("2W", Period.ZERO);
assertEquals(14, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(0, period.getYears());
}

@Test
public void convertToPeriodFromMonths() {
Period period = ChartServlet.convertToPeriod("M", Period.ZERO);
assertEquals(0, period.getDays());
assertEquals(1, period.getMonths());
assertEquals(0, period.getYears());

period = ChartServlet.convertToPeriod("3M", Period.ZERO);
assertEquals(0, period.getDays());
assertEquals(3, period.getMonths());
assertEquals(0, period.getYears());
}

@Test
public void convertToPeriodFromYears() {
Period period = ChartServlet.convertToPeriod("Y", Period.ZERO);
assertEquals(0, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(1, period.getYears());

period = ChartServlet.convertToPeriod("2Y", Period.ZERO);
assertEquals(0, period.getDays());
assertEquals(0, period.getMonths());
assertEquals(2, period.getYears());
}

@Test
public void convertToPeriodFromISO8601() {
Period period = ChartServlet.convertToPeriod("P2Y3M4D", Period.ZERO);
assertEquals(4, period.getDays());
assertEquals(3, period.getMonths());
assertEquals(2, period.getYears());

period = ChartServlet.convertToPeriod("P1DT12H30M15S", Period.ZERO);
assertTrue(period.isZero());
}

@Test
public void convertToDurationFromNull() {
Duration duration = ChartServlet.convertToDuration(null, Duration.ZERO);
assertTrue(duration.isZero());
}

@Test
public void convertToDurationFromHours() {
Duration duration = ChartServlet.convertToDuration("h", Duration.ZERO);
assertEquals(1 * 60 * 60, duration.getSeconds());

duration = ChartServlet.convertToDuration("12h", Duration.ZERO);
assertEquals(12 * 60 * 60, duration.getSeconds());
}

@Test
public void convertToDurationFromDays() {
Duration duration = ChartServlet.convertToDuration("D", Duration.ZERO);
assertEquals(24 * 60 * 60, duration.getSeconds());

duration = ChartServlet.convertToDuration("2D", Duration.ZERO);
assertEquals(48 * 60 * 60, duration.getSeconds());
}

@Test
public void convertToDurationFromWeeks() {
Duration duration = ChartServlet.convertToDuration("2W", Duration.ZERO);
assertTrue(duration.isZero());
}

@Test
public void convertToDurationFromMonths() {
Duration duration = ChartServlet.convertToDuration("3M", Duration.ZERO);
assertTrue(duration.isZero());
}

@Test
public void convertToDurationFromYears() {
Duration duration = ChartServlet.convertToDuration("2Y", Duration.ZERO);
assertTrue(duration.isZero());
}

@Test
public void convertToDurationFromISO8601() {
Duration duration = ChartServlet.convertToDuration("P1DT12H30M15S", Duration.ZERO);
assertEquals(36 * 60 * 60 + 30 * 60 + 15, duration.getSeconds());

duration = ChartServlet.convertToDuration("P2Y3M4D", Duration.ZERO);
assertTrue(duration.isZero());
}
}

0 comments on commit fe68de7

Please sign in to comment.