From 26e03588eaf3eb89271cde3f375c178ceaed8fb7 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 17 Mar 2023 21:16:48 -0700 Subject: [PATCH] Added Uptime --- .github/workflows/gradle.yml | 2 +- .github/workflows/publish.yml | 2 +- README.md | 10 +- .../main/java/rife/render/RenderUtils.java | 71 ++++++++++++++ lib/src/main/java/rife/render/Uptime.java | 94 +++++++++++++++++++ lib/src/test/java/rife/render/TestFormat.java | 22 +++++ lib/src/test/resources/templates/uptime.html | 13 +++ lib/src/test/resources/templates/uptime.json | 1 + lib/src/test/resources/templates/uptime.txt | 6 ++ lib/src/test/resources/templates/uptime2.txt | 14 +++ 10 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 lib/src/main/java/rife/render/Uptime.java create mode 100644 lib/src/test/resources/templates/uptime.html create mode 100644 lib/src/test/resources/templates/uptime.json create mode 100644 lib/src/test/resources/templates/uptime.txt create mode 100644 lib/src/test/resources/templates/uptime2.txt diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9367aec..30f1308 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -31,5 +31,5 @@ jobs: - name: Test with Gradle uses: gradle/gradle-build-action@v2 with: - arguments: build check --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} + arguments: build check --scan --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c9c6e8e..8b957bd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -35,5 +35,5 @@ jobs: ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_signingKey }} ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingPassword }} with: - arguments: build check publish --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} + arguments: build check publish --scan --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} diff --git a/README.md b/README.md index e9dc681..9a0b243 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,12 @@ This project provides a collection of template renderers. ## Format Renderers -| Renderer | Description | -|:---------------------------------|:-----------------------------------------------------------------| -| `rife.render.formatCreditcard` | Formats a template credit card number value to the last 4 digits | -| `rife.render.ShorteUrl` | Shortens a template value using [is./gd](https://is.gd/) | +| Renderer | Description | +|:-------------------------------|:-----------------------------------------------------------------| +| `rife.render.formatCreditcard` | Formats a template credit card number value to the last 4 digits | +| `rife.render.ShorteUrl` | Shortens a template value using [is./gd](https://is.gd/) | +| `rife.render.Uptime` | Renders the server uptime in various customizable formats | + ## Text Renderers diff --git a/lib/src/main/java/rife/render/RenderUtils.java b/lib/src/main/java/rife/render/RenderUtils.java index eb8b869..ade9e9b 100644 --- a/lib/src/main/java/rife/render/RenderUtils.java +++ b/lib/src/main/java/rife/render/RenderUtils.java @@ -27,6 +27,8 @@ import java.nio.charset.StandardCharsets; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal.ChronoField; +import java.util.Properties; +import java.util.concurrent.TimeUnit; /** * Collection of utility-type methods commonly used by the renderers. @@ -118,6 +120,22 @@ public final class RenderUtils { return ""; } + /** + * Returns the plural form of a word, if count > 1. + * + * @param count the count. + * @param word the singular word. + * @param plural the plural word. + * @return the singular or plural string. + */ + public static String plural(final long count, final String word, final String plural) { + if (count > 1) { + return plural; + } else { + return word; + } + } + /** * Translates a String to/from ROT13. * @@ -285,4 +303,57 @@ public final class RenderUtils { return buff.toString(); } + + /** + * Returns the formatted server uptime. + * + * @param uptime the uptime in milliseconds. + * @param properties the format properties. + * @return The formatted uptime. + */ + public static String uptime(long uptime, Properties properties) { + var sb = new StringBuilder(); + + var days = TimeUnit.MILLISECONDS.toDays(uptime); + var years = days / 365; + days %= 365; + var months = days / 30; + days %= 30; + var weeks = days / 7; + days %= 7; + var hours = TimeUnit.MILLISECONDS.toHours(uptime) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(uptime)); + var minutes = TimeUnit.MILLISECONDS.toMinutes(uptime) - TimeUnit.HOURS.toMinutes( + TimeUnit.MILLISECONDS.toHours(uptime)); + + if (years > 0) { + sb.append(years).append(plural(years, properties.getProperty("year", " year "), + properties.getProperty("years", " years "))); + } + + if (months > 0) { + sb.append(months).append(plural(months, properties.getProperty("month", " month "), + properties.getProperty("months", " months "))); + } + + if (weeks > 0) { + sb.append(weeks).append(plural(weeks, properties.getProperty("week", " week "), + properties.getProperty("weeks", " weeks "))); + } + + if (days > 0) { + sb.append(days).append(plural(days, properties.getProperty("day", " day "), + properties.getProperty("days", " days "))); + } + + if (hours > 0) { + sb.append(hours).append(plural(hours, properties.getProperty("hour", " hour "), + properties.getProperty("hours", " hours "))); + } + + sb.append(minutes).append(plural(minutes, properties.getProperty("minute", " minute"), + properties.getProperty("minutes", " minutes"))); + + return sb.toString(); + } + } diff --git a/lib/src/main/java/rife/render/Uptime.java b/lib/src/main/java/rife/render/Uptime.java new file mode 100644 index 0000000..f416aeb --- /dev/null +++ b/lib/src/main/java/rife/render/Uptime.java @@ -0,0 +1,94 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package rife.render; + +import rife.template.Template; +import rife.template.ValueRenderer; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.management.ManagementFactory; +import java.util.Properties; + +/** + * Renders the server uptime. + * + *

Usage:

+ * + *
+ *   <!--v render:rife.render.Uptime/-->
+ *   {{v render:rife.render.Uptime:valueId/}}
+ * 
+ * + *

You can also specify custom formatting using the following properties:

+ * + *
+ *   {{v: render:rife.renader.Uptime}}
+ *   year=Y-
+ *   years=Y-
+ *   month=M-
+ *   months=M-
+ *   week=W-
+ *   weeks=W-
+ *   day=D-
+ *   days=D-
+ *   hour=H-
+ *   hours=H-
+ *   minute=M-
+ *   minutes=M-
+ *   {{/v}}
+ * 
+ * + *

which would render something like

+ * + *
+ *   17Y-2M-2W-1D-9H-33M
+ * 
+ * + *

You can also specify the uptime via a template attribute

+ * + *
+ *   template.setAttribute(Uptime.class.getName(), 120000L);
+ * 
+ * + * @author Erik C. Thauvin + * @since 1.0 + */ +public class Uptime implements ValueRenderer { + /** + * {@inheritDoc} + */ + @Override + public String render(Template template, String valueId, String differentiator) { + var properties = new Properties(); + + if (template.hasDefaultValue(valueId)) { + try { + properties.load(new StringReader(template.getDefaultValue(valueId))); + } catch (IOException ignore) { + // ignore + } + } + + if (template.hasAttribute(Uptime.class.getName())) { + return RenderUtils.uptime((long) template.getAttribute(Uptime.class.getName()), properties); + } else { + return RenderUtils.uptime(ManagementFactory.getRuntimeMXBean().getUptime(), properties); + } + } +} diff --git a/lib/src/test/java/rife/render/TestFormat.java b/lib/src/test/java/rife/render/TestFormat.java index 7153c68..06b6155 100644 --- a/lib/src/test/java/rife/render/TestFormat.java +++ b/lib/src/test/java/rife/render/TestFormat.java @@ -45,6 +45,28 @@ class TestFormat { assertThat(t.getContent()).isEqualTo(String.format("%s", shortUrl, url)); t.setValue(TestCase.FOO, TestCase.FOO); assertThat(t.getContent()).isEqualTo("foo"); + } + + @Test + void testUptime() { + var t = TemplateFactory.TXT.get("uptime"); + assertThat(t.getContent()).matches("0 minute\n0 minuto\n0 minute"); + + t = TemplateFactory.HTML.get("uptime"); + t.setAttribute(Uptime.class.getName(), 547800300076L); + assertThat(t.getContent()).isEqualTo("17 années, 4 mois, 2 semaines, 1 jour, 6 heures, 45 minutes"); + t.setAttribute(Uptime.class.getName(), 120000L); + assertThat(t.getContent()).matches("2 minutes"); + + t = TemplateFactory.JSON.get("uptime"); + t.setAttribute(Uptime.class.getName(), 5999964460000L); + assertThat(t.getContent()).isEqualTo("190 years 3 months 4 days 47 minutes"); + t.setAttribute(Uptime.class.getName(), 34822860000L); + assertThat(t.getContent()).isEqualTo("1 year 1 month 1 week 1 day 1 hour 1 minute"); + + t = TemplateFactory.TXT.get("uptime2"); + t.setAttribute(Uptime.class.getName(), 547800388076L); + assertThat(t.getContent()).matches("17Y-4M-2W-1D-6H-46M"); } } diff --git a/lib/src/test/resources/templates/uptime.html b/lib/src/test/resources/templates/uptime.html new file mode 100644 index 0000000..f8232e7 --- /dev/null +++ b/lib/src/test/resources/templates/uptime.html @@ -0,0 +1,13 @@ + +year=\ année,\u0020 +years=\ années,\u0020 +month=\ moi,\u0020 +months=\ mois,\u0020 +week=\ semaine,\u0020 +weeks=\ semaines,\u0020 +day=\ jour,\u0020 +days=\ jours,\u0020 +hour=\ heure,\u0020 +hours=\ heures,\u0020 +minute=\ minute +minutes=\ minutes \ No newline at end of file diff --git a/lib/src/test/resources/templates/uptime.json b/lib/src/test/resources/templates/uptime.json new file mode 100644 index 0000000..84c7b37 --- /dev/null +++ b/lib/src/test/resources/templates/uptime.json @@ -0,0 +1 @@ +{{v render:rife.render.Uptime/}} \ No newline at end of file diff --git a/lib/src/test/resources/templates/uptime.txt b/lib/src/test/resources/templates/uptime.txt new file mode 100644 index 0000000..826ae12 --- /dev/null +++ b/lib/src/test/resources/templates/uptime.txt @@ -0,0 +1,6 @@ +{{v render:rife.render.Uptime/}} +{{v render:rife.render.Uptime:spanish}} +minute=\ minuto +minutes=\ minutos +{{/v}} +{{v render:rife.render.Uptime:plain}}{{/v}} \ No newline at end of file diff --git a/lib/src/test/resources/templates/uptime2.txt b/lib/src/test/resources/templates/uptime2.txt new file mode 100644 index 0000000..635467c --- /dev/null +++ b/lib/src/test/resources/templates/uptime2.txt @@ -0,0 +1,14 @@ +{{v render:rife.render.Uptime}} +year=Y- +years=Y- +month=M- +months=M- +week=W- +weeks=W- +day=D- +days=D- +hour=H- +hours=H- +minute=M +minutes=M +{{/v}} \ No newline at end of file