Repository: jmrozanec/cron-utils
Pull request #349 (2018-10-05 12:23:43)

#291 - modify cron parser building possible expressions logic 
to support multiple, not only one optional field in cron definition.


Patch:
diff --git a/src/main/java/com/cronutils/parser/CronParser.java b/src/main/java/com/cronutils/parser/CronParser.java
index f229b71..29f1ed6 100755
--- a/src/main/java/com/cronutils/parser/CronParser.java
+++ b/src/main/java/com/cronutils/parser/CronParser.java
@@ -58,9 +58,16 @@ public class CronParser {
                 .sorted(CronParserField.createFieldTypeComparator())
                 .collect(Collectors.toList());
 
-        if (lastFieldIsOptional(sortedExpression)) {
-            expressions.put(sortedExpression.size() - 1, new ArrayList<>(sortedExpression.subList(0, sortedExpression.size() - 1)));
+        List<CronParserField> tempExpression = sortedExpression;
+
+        while(lastFieldIsOptional(tempExpression)) {
+            int expressionLength = tempExpression.size() - 1;
+            ArrayList<CronParserField> possibleExpression = new ArrayList<>(tempExpression.subList(0, expressionLength));
+
+            expressions.put(expressionLength, possibleExpression);
+            tempExpression = possibleExpression;
         }
+
         expressions.put(sortedExpression.size(), sortedExpression);
     }
 


Test patch:
diff --git a/src/test/java/com/cronutils/model/time/ExecutionTimeCustomDefinitionIntegrationTest.java b/src/test/java/com/cronutils/model/time/ExecutionTimeCustomDefinitionIntegrationTest.java
index e7dc50c..7d001c6 100755
--- a/src/test/java/com/cronutils/model/time/ExecutionTimeCustomDefinitionIntegrationTest.java
+++ b/src/test/java/com/cronutils/model/time/ExecutionTimeCustomDefinitionIntegrationTest.java
@@ -215,7 +215,7 @@ public class ExecutionTimeCustomDefinitionIntegrationTest {
      * with 4 fields as an error:
      * java.lang.IllegalArgumentException: Cron expression contains 4 parts but we expect one of [6, 7]
      */
-    //@Test //FIXME issue #291
+    @Test
     public void testThreeRequiredFieldsSupported() {
         final CronDefinition cronDefinition = CronDefinitionBuilder.defineCron()
                 .withSeconds().and()
@@ -230,4 +230,25 @@ public class ExecutionTimeCustomDefinitionIntegrationTest {
         final CronParser cronParser = new CronParser(cronDefinition);
         cronParser.parse("* * 4 3");
     }
+
+    /**
+     * A CronDefinition with only 5 required fields is legal to instantiate, but the parser considers an expression
+     * with 5 fields as an error:
+     * java.lang.IllegalArgumentException: Cron expression contains 4 parts but we expect one of [6, 7]
+     */
+    @Test
+    public void testFiveRequiredFieldsSupported() {
+        final CronDefinition cronDefinition = CronDefinitionBuilder.defineCron()
+                .withSeconds().and()
+                .withMinutes().and()
+                .withHours().and()
+                .withDayOfMonth().supportsL().supportsW().supportsLW().supportsQuestionMark().and()
+                .withMonth().and()
+                .withDayOfWeek().withValidRange(1, 7).withMondayDoWValue(2).supportsHash().supportsL()
+                .supportsQuestionMark().optional().and()
+                .withYear().withValidRange(2000, 2099).optional().and()
+                .instance();
+        final CronParser cronParser = new CronParser(cronDefinition);
+        cronParser.parse("* * 4 3 *");
+    }
 }