Skip to content

Commit

Permalink
[sitemap] Extend chart periods to cover past and future
Browse files Browse the repository at this point in the history
Closes openhab/openhab-webui#2518

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo committed Apr 6, 2024
1 parent 875ebaa commit fb5f7c1
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ public class RESTConstants {
* Version 4: OH3, refactored extensions to addons (#1560)
* Version 5: transparent charts (#2502)
* Version 6: extended chart period parameter format (#3863)
* Version 7: extended chart period parameter format to cover past and future
*/
public static final String API_VERSION = "6";
public static final String API_VERSION = "7";

public static final CacheControl CACHE_CONTROL = new CacheControl();
static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Chart:
(('icon=' icon=Icon) |
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
('staticIcon=' staticIcon=Icon))? &
('service=' service=STRING)? & ('refresh=' refresh=INT)? & ('period=' period=ID) &
('service=' service=STRING)? & ('refresh=' refresh=INT)? & ('period=' period=Period) &
('legend=' legend=BOOLEAN_OBJECT)? & ('forceasitem=' forceAsItem=BOOLEAN_OBJECT)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
Expand Down Expand Up @@ -222,6 +222,9 @@ Icon returns ecore::EString:
IconName:
(ID '-')* ID;

Period:
(ID '-')? ID;

ColorArray:
((conditions+=Condition ('AND' conditions+=Condition)*) '=')? (arg=STRING);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,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
* @author Laurent Garnier - Extend support to past and future 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 @@ -100,7 +101,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);
protected static final Duration DEFAULT_PERIOD = Duration.ofDays(1);

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

Expand Down Expand Up @@ -216,15 +217,14 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser
String periodParam = req.getParameter("period");
String timeBeginParam = req.getParameter("begin");
String timeEndParam = req.getParameter("end");

// To avoid ambiguity you are not allowed to specify period, begin and end time at the same time.
if (periodParam != null && timeBeginParam != null && timeEndParam != null) {
res.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Do not specify the three parameters period, begin and end at the same time.");
return;
}

// Read out the parameter period, begin and end and save them.
TemporalAmount period = convertToTemporalAmount(periodParam, DEFAULT_PERIOD);
ZonedDateTime timeBegin = null;
ZonedDateTime timeEnd = null;

Expand All @@ -248,18 +248,11 @@ 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);
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);
logger.debug("No end is specified, use begin + period as end.");
} else if (timeBegin == null) {
timeBegin = timeEnd.minus(period);
logger.debug("No begin is specified, use end-period as begin");
} else if (timeEnd.isBefore(timeBegin)) {
PeriodPastFuture period = getPeriodPastFuture(periodParam);
PeriodBeginEnd beginEnd = getPeriodBeginEnd(timeBegin, timeEnd, period,
ZonedDateTime.now(timeZoneProvider.getTimeZone()));

if (beginEnd.begin() != null && beginEnd.end() != null && beginEnd.end().isBefore(beginEnd.begin())) {
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "The end is before the begin.");
return;
}
Expand Down Expand Up @@ -308,9 +301,9 @@ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws Ser

logger.debug("chart building with width {} height {} dpi {}", width, height, dpi);
try {
BufferedImage chart = provider.createChart(serviceName, req.getParameter("theme"), timeBegin, timeEnd,
height, width, req.getParameter("items"), req.getParameter("groups"), dpi, yAxisDecimalPattern,
legend);
BufferedImage chart = provider.createChart(serviceName, req.getParameter("theme"), beginEnd.begin(),
beginEnd.end(), height, width, req.getParameter("items"), req.getParameter("groups"), dpi,
yAxisDecimalPattern, legend);
// Set the content type to that provided by the chart provider
res.setContentType("image/" + provider.getChartType());
try (ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(res.getOutputStream())) {
Expand Down Expand Up @@ -351,7 +344,8 @@ public void init(@Nullable ServletConfig config) throws ServletException {
public void destroy() {
}

public static TemporalAmount convertToTemporalAmount(@Nullable String periodParam, TemporalAmount defaultPeriod) {
protected static @Nullable TemporalAmount convertToTemporalAmount(@Nullable String periodParam,
@Nullable TemporalAmount defaultPeriod) {
TemporalAmount period = defaultPeriod;
String convertedPeriod = convertPeriodToISO8601(periodParam);
if (convertedPeriod != null) {
Expand Down Expand Up @@ -383,4 +377,70 @@ public static TemporalAmount convertToTemporalAmount(@Nullable String periodPara
}
return "P" + newPeriod;
}

protected static PeriodPastFuture getPeriodPastFuture(@Nullable String periodParam) {
String periodParamPast = null;
String periodParamFuture = null;
TemporalAmount defaultPeriodPast = DEFAULT_PERIOD;
TemporalAmount defaultPeriodFuture = null;
if (periodParam != null) {
int idx = periodParam.indexOf("-");
if (idx < 0) {
periodParamPast = periodParam;
} else {
if (idx > 0) {
periodParamPast = periodParam.substring(0, idx);
} else {
defaultPeriodPast = null;
defaultPeriodFuture = DEFAULT_PERIOD;
}
periodParamFuture = periodParam.substring(idx + 1);
}
}
TemporalAmount periodPast = convertToTemporalAmount(periodParamPast, defaultPeriodPast);
TemporalAmount periodFuture = convertToTemporalAmount(periodParamFuture, defaultPeriodFuture);
return new PeriodPastFuture(periodPast, periodFuture);
}

protected static PeriodBeginEnd getPeriodBeginEnd(@Nullable ZonedDateTime begin, @Nullable ZonedDateTime end,
PeriodPastFuture period, ZonedDateTime now) {
ZonedDateTime timeBegin = begin;
ZonedDateTime timeEnd = end;
TemporalAmount periodPast = period.past();
TemporalAmount periodFuture = period.future();

if (timeBegin == null && timeEnd == null) {
timeBegin = timeEnd = now;
if (periodPast != null) {
timeBegin = timeBegin.minus(periodPast);
}
if (periodFuture != null) {
timeEnd = timeEnd.plus(periodFuture);
}
} else if (timeBegin != null && timeEnd == null) {
timeEnd = timeBegin;
if (periodPast != null) {
timeEnd = timeEnd.plus(periodPast);
}
if (periodFuture != null) {
timeEnd = timeEnd.plus(periodFuture);
}
} else if (timeBegin == null && timeEnd != null) {
timeBegin = timeEnd;
if (periodFuture != null) {
timeBegin = timeBegin.minus(periodFuture);
}
if (periodPast != null) {
timeBegin = timeBegin.minus(periodPast);
}
}

return new PeriodBeginEnd(Objects.requireNonNull(timeBegin), Objects.requireNonNull(timeEnd));
}

record PeriodPastFuture(@Nullable TemporalAmount past, @Nullable TemporalAmount future) {
}

record PeriodBeginEnd(ZonedDateTime begin, ZonedDateTime end) {
}
}

0 comments on commit fb5f7c1

Please sign in to comment.