diff --git a/.classpath b/.classpath
index 76fc9c8..f6013c0 100644
--- a/.classpath
+++ b/.classpath
@@ -99,5 +99,6 @@
+
diff --git a/src/main/java/com/mousetech/gourmetj/RecipeDetailBean.java b/src/main/java/com/mousetech/gourmetj/RecipeDetailBean.java
index 3ea29c2..c21665e 100644
--- a/src/main/java/com/mousetech/gourmetj/RecipeDetailBean.java
+++ b/src/main/java/com/mousetech/gourmetj/RecipeDetailBean.java
@@ -215,8 +215,6 @@ public class RecipeDetailBean implements Serializable {
@PostConstruct
private void init() {
this.recipe = userSession.getRecipe();
-
- log.info("Using recipe: " + this.recipe);
/**
* For "create new, this recipe is a blank constructed
* and passed from main page. For Detail display, it's
diff --git a/src/main/java/com/mousetech/gourmetj/UserSession.java b/src/main/java/com/mousetech/gourmetj/UserSession.java
index eb21410..0e4af9c 100644
--- a/src/main/java/com/mousetech/gourmetj/UserSession.java
+++ b/src/main/java/com/mousetech/gourmetj/UserSession.java
@@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
import com.mousetech.gourmetj.persistence.model.Category;
import com.mousetech.gourmetj.persistence.model.Recipe;
+import com.mousetech.gourmetj.utils.TimeFormatter;
@Named
@SessionScoped
@@ -123,46 +124,15 @@ public class UserSession implements Serializable {
return sb.toString();
}
+ //** Util, consider conversion to JSF Converter
public String formatTime(Long ltime) {
- if (ltime == null) {
- return "";
- }
- int time = ltime.intValue();
- int dd, hh, mm, ss;
- ss = time % 60;
- time /= 60;
- mm = time % 60;
- time /= 60;
- hh = time % 24;
- dd = time / 24;
- StringBuffer sb = new StringBuffer(20);
- if (dd > 0) {
- sb.append(dd).append("d ");
- }
- if (hh > 0) {
- sb.append(hh).append("h ");
- }
- if (mm > 0) {
- sb.append(mm);
- if ((ss == 0) && (hh == 0)) {
- sb.append(" minutes");
- } else {
- sb.append("min. ");
- }
- }
- if (ss > 0) {
- sb.append(dd).append("sec. ");
- }
- return sb.toString().trim();
+ return TimeFormatter.formatTime(ltime);
}
// Primefaces handle session timeout
-
- /**
- * Session timeout, msec.
- */
- private long sessionTimeoutInterval = 300000;
-
+ // Session timeout, ms
+ long sessionTimeoutInterval = 30000L;
+
/**
* @return the sessionTimeoutInterval
*/
@@ -176,7 +146,8 @@ public class UserSession implements Serializable {
.executeScript("sessionExpiredConfirmation.show()");
}
- public void logoutAction() {
+ public String logoutAction() {
log.warn("Session Idle listener logout");
+ return "/main.jsf";
}
}
diff --git a/src/main/java/com/mousetech/gourmetj/utils/TimeFormatter.java b/src/main/java/com/mousetech/gourmetj/utils/TimeFormatter.java
new file mode 100644
index 0000000..13be7b0
--- /dev/null
+++ b/src/main/java/com/mousetech/gourmetj/utils/TimeFormatter.java
@@ -0,0 +1,181 @@
+package com.mousetech.gourmetj.utils;
+
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handle conversion of complex time fields where days, hours,
+ * minutes and seconds may be present as separate entities.
+ *
+ * @author timh
+ * @since Jan 8, 2022
+ */
+public class TimeFormatter {
+
+ /* Logger */
+
+ private static final Logger log =
+ LoggerFactory.getLogger(TimeFormatter.class);
+
+ public static String formatTime(Long ltime) {
+ if (ltime == null) {
+ return "";
+ }
+ int time = ltime.intValue();
+ int dd, hh, mm, ss;
+ ss = time % 60;
+ time /= 60;
+ mm = time % 60;
+ time /= 60;
+ hh = time % 24;
+ dd = time / 24;
+ StringBuffer sb = new StringBuffer(20);
+ if (dd > 0) {
+ sb.append(dd).append("d ");
+ }
+ if (hh > 0) {
+ sb.append(hh).append("h ");
+ }
+ if (mm > 0) {
+ sb.append(mm);
+ if ((ss == 0) && (hh == 0)) {
+ sb.append(" minutes");
+ } else {
+ sb.append("min. ");
+ }
+ }
+ if (ss > 0) {
+ sb.append(dd).append("sec. ");
+ }
+ return sb.toString().trim();
+ }
+
+// private enum MunchUnit {
+// mu_NONE, mu_DAY, mu_HOUR, mu_MINUTE, mw_SECOND
+// }
+
+ private static class TimeMuncher {
+
+ public class MunchException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ final private String SPAT_DAYS = "days?|d";
+ final private String SPAT_HOURS = "hours?|h|hr";
+ final private String SPAT_MINUTES = "minutes?|mins?|m";
+ final private String SPAT_SECONDS = "seconds?|secs?|s";
+
+ final Pattern pat_number;
+ final Pattern pat_days;
+ final Pattern pat_hours;
+ final Pattern pat_mins;
+ final Pattern pat_secs;
+
+ final Scanner scanner;
+
+ public TimeMuncher(String timestr) {
+ pat_number =
+ Pattern.compile("(\\d[\\,\\.]?\\d*)?(.*)");
+ // Compile here for future I18N support
+ pat_days = Pattern.compile(SPAT_DAYS);
+ pat_hours = Pattern.compile(SPAT_HOURS);
+ pat_mins = Pattern.compile(SPAT_MINUTES);
+ pat_secs = Pattern.compile(SPAT_SECONDS);
+
+ scanner = new Scanner(timestr);
+ scanner.useDelimiter("\\W");
+ }
+
+ public Long scan() {
+ Double sum = null;
+ Double dvalue = null;
+
+ try {
+ while (scanner.hasNext()) {
+ if (scanner.hasNextDouble()) {
+ dvalue = scanner.nextDouble();
+ } else {
+ String units = scanner.next();
+ sum = setSum(sum, dvalue, units);
+ dvalue = null;
+ }
+ }
+ } catch (MunchException e) {
+ log.warn("Unparseable time value");
+ e.printStackTrace();
+ }
+ if (sum == null) {
+ return null;
+ }
+ return sum.longValue();
+ }
+
+ private Double setSum(Double sum, Double dvalue,
+ String units) throws MunchException {
+ Matcher m;
+
+ m = pat_number.matcher(units);
+
+ if (!m.matches()) {
+ throw new MunchException();
+ }
+ if (m.group(1) != null) {
+ String a = m.group(1);
+ if (dvalue != null) {
+ throw new MunchException();
+ }
+ dvalue = Double
+ .valueOf(a);
+ //units = units.substring(m.end());
+ }
+ units = m.group(2);
+ m = pat_days.matcher(units);
+ if (m.matches()) {
+ return addToSum(sum, dvalue,
+ 24L * 60L * 60L * 1000L);
+ }
+ m = pat_hours.matcher(units);
+ if (m.matches()) {
+ return addToSum(sum, dvalue, 60L * 60L * 1000L);
+ }
+ m = pat_mins.matcher(units);
+ if (m.matches()) {
+ return addToSum(sum, dvalue, 60L * 1000L);
+ }
+ m = pat_secs.matcher(units);
+ if (m.matches()) {
+ return addToSum(sum, dvalue, 1000L);
+ }
+ return sum;
+ }
+
+ private Double addToSum(Double sum, Double dvalue,
+ long l) throws MunchException {
+ if (dvalue == null) {
+ throw new TimeMuncher.MunchException();
+ }
+ dvalue *= l;
+ if (sum == null) {
+ sum = 0.0;
+ }
+ sum += dvalue;
+ return sum;
+ }
+ }
+
+ public static Long parseTime(String timestr) {
+ TimeMuncher muncher = new TimeMuncher(timestr);
+
+ Long interval = muncher.scan();
+ return interval;
+ }
+}
diff --git a/src/main/java/com/mousetech/gourmetj/utils/package-info.java b/src/main/java/com/mousetech/gourmetj/utils/package-info.java
new file mode 100644
index 0000000..410ff17
--- /dev/null
+++ b/src/main/java/com/mousetech/gourmetj/utils/package-info.java
@@ -0,0 +1 @@
+package com.mousetech.gourmetj.utils;
diff --git a/src/main/resources/META-INF/resources/WEB-INF/layout/layout.xhtml b/src/main/resources/META-INF/resources/WEB-INF/layout/layout.xhtml
index 1a63bc7..d537bf7 100644
--- a/src/main/resources/META-INF/resources/WEB-INF/layout/layout.xhtml
+++ b/src/main/resources/META-INF/resources/WEB-INF/layout/layout.xhtml
@@ -40,16 +40,16 @@
-
diff --git a/src/main/resources/META-INF/resources/detailEdit.xhtml b/src/main/resources/META-INF/resources/detailEdit.xhtml
index af80892..f9a139c 100644
--- a/src/main/resources/META-INF/resources/detailEdit.xhtml
+++ b/src/main/resources/META-INF/resources/detailEdit.xhtml
@@ -360,10 +360,12 @@
diff --git a/src/main/resources/META-INF/resources/error/viewExpired.html b/src/main/resources/META-INF/resources/error/viewExpired.html
index b1a8cba..5ebdb02 100644
--- a/src/main/resources/META-INF/resources/error/viewExpired.html
+++ b/src/main/resources/META-INF/resources/error/viewExpired.html
@@ -1,13 +1,14 @@
-
ERROR - Page Expired
Page Expired
- The page state could not be restored because it was left
- idle too long.
- Return to Main Page
+ The page state could not be restored because it was
+ left idle too long.
+
+ Return to Main Page
+
-
+
\ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/recipeDetails.xhtml b/src/main/resources/META-INF/resources/recipeDetails.xhtml
index 581bde0..2f6d5d5 100644
--- a/src/main/resources/META-INF/resources/recipeDetails.xhtml
+++ b/src/main/resources/META-INF/resources/recipeDetails.xhtml
@@ -45,12 +45,12 @@
columns="2"
>
-
+ */
+package com.mousetech.gourmetj.utils;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author timh
+ * @since Jan 8, 2022
+ */
+class TimeFormatterTest {
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeAll
+ static void setUpBeforeClass() throws Exception {
+ }
+
+ @Test
+ void test() {
+ assertEquals(5000, TimeFormatter.parseTime("5s"));
+ assertEquals(5000*60, TimeFormatter.parseTime("5m"));
+
+ assertEquals(3600_000 + 25*60_000, TimeFormatter.parseTime("1 hour, 25 min"));
+
+ assertEquals(5*3600000 + 6*60000, TimeFormatter.parseTime("5h 6m"));
+ assertEquals(277562000L, TimeFormatter.parseTime("3d 5h 6m 2s"));
+
+ assertEquals(18000000L, TimeFormatter.parseTime("1.5 hours"));
+
+ assertEquals(3*3600_000, TimeFormatter.parseTime("3 hours"));
+
+ assertNull(TimeFormatter.parseTime("1 week"));
+ }
+
+}