This is an automated email from the ASF dual-hosted git repository.

gitgabrio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new e1fc1b4a53 [incubator-kie-issues#506] DMN - Add support for iteration 
of date ranges (#5626)
e1fc1b4a53 is described below

commit e1fc1b4a534e28af31ebeb93a0dcc128180a3ccb
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Tue Jan 9 09:48:45 2024 +0100

    [incubator-kie-issues#506] DMN - Add support for iteration of date ranges 
(#5626)
    
    * [incubator-kie-issues#506] Implemented Date iteration. Refactored to 
remove duplicated code and allow easy extension of use cases
    
    * [incubator-kie-issues#506] WIP
    
    * [incubator-kie-issues#506] Update with main. Add unit tests
    
    * [incubator-kie-issues#506] WIP
    
    * [incubator-kie-issues#506] Restored code-level 11 syntax
    
    * [incubator-kie-issues#506] Merged with main
    
    * [incubator-kie-issues#506] Fix as per PR suggestion
    
    ---------
    
    Co-authored-by: BAMOE CI <[email protected]>
---
 .../feel/codegen/feel11/CompiledFEELSupport.java   |  44 ++---
 .../EndpointOfRangeNotOfNumberException.java       |  22 +++
 .../EndpointOfRangeNotValidTypeException.java      |  23 +++
 .../EndpointOfRangeOfDifferentTypeException.java   |  23 +++
 .../kie/dmn/feel/lang/ast/ForExpressionNode.java   | 180 +++++----------------
 .../BigDecimalRangeIterator.java                   |  69 ++++++++
 .../lang/ast/forexpressioniterators/Direction.java |  24 +++
 .../ast/forexpressioniterators/ForIteration.java   |  67 ++++++++
 .../forexpressioniterators/ForIterationUtils.java  |  66 ++++++++
 .../LocalDateRangeIterator.java                    |  67 ++++++++
 .../ZonedDateTimeRangeIterator.java                |  69 ++++++++
 .../feel/lang/ast/infixexecutors/AddExecutor.java  |  44 ++---
 .../feel/lang/ast/infixexecutors/AndExecutor.java  |   6 +-
 .../feel/lang/ast/infixexecutors/OrExecutor.java   |   6 +-
 .../src/main/java/org/kie/dmn/feel/util/Msg.java   |   2 +-
 .../BigDecimalRangeIteratorTest.java               |  81 ++++++++++
 .../forexpressioniterators/ForIterationTest.java   |  80 +++++++++
 .../ForIterationUtilsTest.java                     | 154 ++++++++++++++++++
 .../LocalDateRangeIteratorTest.java                |  83 ++++++++++
 .../ZonedDateTimeRangeIteratorTest.java            | 115 +++++++++++++
 .../feel/runtime/FEEL12ExtendedForLoopTest.java    |  38 ++---
 21 files changed, 1050 insertions(+), 213 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSupport.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSupport.java
index 99785c4508..4224ad2be2 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSupport.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSupport.java
@@ -18,16 +18,6 @@
  */
 package org.kie.dmn.feel.codegen.feel11;
 
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-
 import ch.obermuhlner.math.big.BigDecimalMath;
 import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.NodeList;
@@ -46,12 +36,14 @@ import com.github.javaparser.ast.type.UnknownType;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
 import org.kie.dmn.api.feel.runtime.events.FEELEventListener;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeNotValidTypeException;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeOfDifferentTypeException;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.ast.ForExpressionNode;
-import org.kie.dmn.feel.lang.ast.ForExpressionNode.ForIteration;
 import org.kie.dmn.feel.lang.ast.QuantifiedExpressionNode;
 import org.kie.dmn.feel.lang.ast.QuantifiedExpressionNode.QEIteration;
 import org.kie.dmn.feel.lang.ast.QuantifiedExpressionNode.Quantifier;
+import org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIteration;
 import org.kie.dmn.feel.lang.impl.SilentWrappingEvaluationContextImpl;
 import org.kie.dmn.feel.lang.types.BuiltInType;
 import org.kie.dmn.feel.runtime.FEELFunction;
@@ -64,8 +56,19 @@ import org.kie.dmn.feel.util.EvalHelper;
 import org.kie.dmn.feel.util.Msg;
 import org.kie.dmn.feel.util.MsgUtil;
 
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
 import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
 import static 
org.kie.dmn.feel.codegen.feel11.Expressions.compiledFeelSemanticMappingsFQN;
+import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils.getForIteration;
 
 public class CompiledFEELSupport {
 
@@ -265,7 +268,7 @@ public class CompiledFEELSupport {
                     ctx.exitFrame(); // last i-th scope unrolled, see also 
ForExpressionNode.nextIteration(...)
                 }
                 return results;
-            } catch (EndpointOfRangeNotOfNumberException e) {
+            } catch (EndpointOfRangeNotValidTypeException | 
EndpointOfRangeOfDifferentTypeException e) {
                 // ast error already reported
                 return null;
             } finally {
@@ -296,26 +299,11 @@ public class CompiledFEELSupport {
                 Iterable values = result instanceof Iterable ? (Iterable) 
result : Collections.singletonList(result);
                 fi = new ForIteration(name, values);
             } else {
-                valueMustBeANumber(ctx, result);
-                BigDecimal start = (BigDecimal) result;
-                valueMustBeANumber(ctx, rangeEnd);
-                BigDecimal end = (BigDecimal) rangeEnd;
-                fi = new ForIteration(name, start, end);
+                fi = getForIteration(ctx, name, result, rangeEnd);
             }
             return fi;
         }
 
-        private void valueMustBeANumber(EvaluationContext ctx, Object value) {
-            if (!(value instanceof BigDecimal)) {
-                ctx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, 
Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER,
 value), null));
-                throw new EndpointOfRangeNotOfNumberException();
-            }
-        }
-
-        private static class EndpointOfRangeNotOfNumberException extends 
RuntimeException {
-
-            private static final long serialVersionUID = 1L;
-        }
     }
 
     public static class IterationContextCompiled {
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotOfNumberException.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotOfNumberException.java
new file mode 100644
index 0000000000..3c6ce52b78
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotOfNumberException.java
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.exceptions;
+
+public class EndpointOfRangeNotOfNumberException extends RuntimeException {
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotValidTypeException.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotValidTypeException.java
new file mode 100644
index 0000000000..f49115f618
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeNotValidTypeException.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.exceptions;
+
+public class EndpointOfRangeNotValidTypeException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeOfDifferentTypeException.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeOfDifferentTypeException.java
new file mode 100644
index 0000000000..4c62799bea
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/exceptions/EndpointOfRangeOfDifferentTypeException.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.exceptions;
+
+public class EndpointOfRangeOfDifferentTypeException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
index d92fed9c19..9b062179b1 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
@@ -18,34 +18,33 @@
  */
 package org.kie.dmn.feel.lang.ast;
 
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.function.Supplier;
-
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeNotValidTypeException;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeOfDifferentTypeException;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.Type;
+import org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIteration;
 import org.kie.dmn.feel.lang.types.BuiltInType;
-import org.kie.dmn.feel.util.Msg;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils.getForIteration;
 
 public class ForExpressionNode
         extends BaseNode {
 
+
     private List<IterationContextNode> iterationContexts;
-    private BaseNode                   expression;
+    private BaseNode expression;
 
     public ForExpressionNode(ParserRuleContext ctx, ListNode 
iterationContexts, BaseNode expression) {
-        super( ctx );
-        this.iterationContexts = new ArrayList<>(  );
+        super(ctx);
+        this.iterationContexts = new ArrayList<>();
         this.expression = expression;
-        for( BaseNode n : iterationContexts.getElements() ) {
-            this.iterationContexts.add( (IterationContextNode) n );
+        for (BaseNode n : iterationContexts.getElements()) {
+            this.iterationContexts.add((IterationContextNode) n);
         }
     }
 
@@ -69,17 +68,17 @@ public class ForExpressionNode
     public Object evaluate(EvaluationContext ctx) {
         try {
             ctx.enterFrame();
-            List results = new ArrayList(  );
+            List results = new ArrayList();
             ctx.setValue("partial", results);
-            ForIteration[] ictx = initializeContexts( ctx, iterationContexts);
+            ForIteration[] ictx = initializeContexts(ctx, iterationContexts);
 
-            while ( nextIteration( ctx, ictx ) ) {
-                Object result = expression.evaluate( ctx );
-                results.add( result );
+            while (nextIteration(ctx, ictx)) {
+                Object result = expression.evaluate(ctx);
+                results.add(result);
                 ctx.exitFrame(); // last i-th scope unrolled, see also 
ForExpressionNode.nextIteration(...)
             }
             return results;
-        } catch (EndpointOfRangeNotOfNumberException e) {
+        } catch (EndpointOfRangeNotValidTypeException | 
EndpointOfRangeOfDifferentTypeException e) {
             // ast error already reported
             return null;
         } finally {
@@ -88,18 +87,18 @@ public class ForExpressionNode
     }
 
     public static boolean nextIteration(EvaluationContext ctx, ForIteration[] 
ictx) {
-        int i = ictx.length-1;
-        while ( i >= 0 && i < ictx.length ) {
-            if ( ictx[i].hasNextValue() ) {
+        int i = ictx.length - 1;
+        while (i >= 0 && i < ictx.length) {
+            if (ictx[i].hasNextValue()) {
                 ctx.enterFrame(); // on first iter, open last scope frame; or 
new ones when prev unrolled
-                setValueIntoContext( ctx, ictx[i] );
+                setValueIntoContext(ctx, ictx[i]);
                 i++;
             } else {
-                if ( i > 0 ) {
+                if (i > 0) {
                     // end of iter loop for this i-th scope; i-th scope is 
always unrolled as part of the 
                     // for-loop cycle, so here must unroll the _prev_ scope;
                     // the if-guard for this code block makes sure NOT to 
unroll bottom one.
-                    ctx.exitFrame();         
+                    ctx.exitFrame();
                 }
                 i--;
             }
@@ -108,9 +107,9 @@ public class ForExpressionNode
     }
 
     public static void setValueIntoContext(EvaluationContext ctx, ForIteration 
forIteration) {
-        ctx.setValue( forIteration.getName(), forIteration.getNextValue() );
+        ctx.setValue(forIteration.getName(), forIteration.getNextValue());
     }
-    
+
     @Override
     public Type getResultType() {
         return BuiltInType.LIST;
@@ -119,139 +118,36 @@ public class ForExpressionNode
     private ForIteration[] initializeContexts(EvaluationContext ctx, 
List<IterationContextNode> iterationContexts) {
         ForIteration[] ictx = new ForIteration[iterationContexts.size()];
         int i = 0;
-        for ( IterationContextNode icn : iterationContexts ) {
-            ictx[i] = createQuantifiedExpressionIterationContext( ctx, icn );
-            if( i < iterationContexts.size()-1 && ictx[i].hasNextValue() ) {
+        for (IterationContextNode icn : iterationContexts) {
+            ictx[i] = createQuantifiedExpressionIterationContext(ctx, icn);
+            if (i < iterationContexts.size() - 1 && ictx[i].hasNextValue()) {
                 ctx.enterFrame(); // open loop scope frame, for every iter 
ctx, except last one as guarded by if clause above
-                setValueIntoContext( ctx, ictx[i] );
+                setValueIntoContext(ctx, ictx[i]);
             }
             i++;
         }
         return ictx;
     }
 
-    private static class EndpointOfRangeNotOfNumberException extends 
RuntimeException {
-        private static final long serialVersionUID = 1L;
-    }
-
     private ForIteration 
createQuantifiedExpressionIterationContext(EvaluationContext ctx, 
IterationContextNode icn) {
         ForIteration fi;
-        String name = icn.evaluateName( ctx );
-        Object result = icn.evaluate( ctx );
+        String name = icn.evaluateName(ctx);
+        Object result = icn.evaluate(ctx);
         Object rangeEnd = icn.evaluateRangeEnd(ctx);
         if (rangeEnd == null) {
             Iterable values = result instanceof Iterable ? (Iterable) result : 
Collections.singletonList(result);
             fi = new ForIteration(name, values);
         } else {
-            valueMustBeANumber(ctx, result);
-            BigDecimal start = (BigDecimal) result;
-            valueMustBeANumber(ctx, rangeEnd);
-            BigDecimal end = (BigDecimal) rangeEnd;
-            fi = new ForIteration(name, start, end);
+            fi = getForIteration(ctx, name, result, rangeEnd);
         }
         return fi;
     }
 
-    private void valueMustBeANumber(EvaluationContext ctx, Object value) {
-        if (!(value instanceof BigDecimal)) {
-            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER,
 value), null));
-            throw new EndpointOfRangeNotOfNumberException();
-        }
-    }
-
-    public static class ForIteration {
-        private String   name;
-        private Iterable values;
-
-        private Supplier<Iterator> iteratorGenerator;
-        private Iterator iterator;
-
-        public ForIteration(String name, Iterable values) {
-            this.name = name;
-            this.values = values;
-            this.iteratorGenerator = () -> this.values.iterator();
-        }
-
-        public ForIteration(String name, final BigDecimal start, final 
BigDecimal end) {
-            this.name = name;
-            this.iteratorGenerator = () -> new BigDecimalRangeIterator(start, 
end);
-        }
-
-        public boolean hasNextValue() {
-            if( iterator == null ) {
-                iterator = iteratorGenerator.get();
-            }
-            boolean hasValue = this.iterator.hasNext();
-            if( ! hasValue ) {
-                this.iterator = null;
-            }
-            return hasValue;
-        }
-
-        public Object getNextValue() {
-            return iterator != null ? iterator.next() : null;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    public static class BigDecimalRangeIterator implements 
Iterator<BigDecimal> {
-
-        private enum Direction {
-            ASCENDANT,
-            DESCENDANT;
-        }
-
-        private final BigDecimal start;
-        private final BigDecimal end;
-
-        private BigDecimal cursor;
-        private final Direction direction;
-        private final BigDecimal increment;
-
-        public BigDecimalRangeIterator(BigDecimal start, BigDecimal end) {
-            this.start = start;
-            this.end = end;
-            this.direction = (start.compareTo(end) <= 0) ? Direction.ASCENDANT 
: Direction.DESCENDANT;
-            this.increment = (direction == Direction.ASCENDANT) ? new 
BigDecimal(1, MathContext.DECIMAL128) : new BigDecimal(-1, 
MathContext.DECIMAL128);
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (cursor == null) {
-                return true;
-            } else {
-                BigDecimal lookAhead = cursor.add(increment);
-                if (direction == Direction.ASCENDANT) {
-                    return lookAhead.compareTo(end) <= 0;
-                } else {
-                    return lookAhead.compareTo(end) >= 0;
-                }
-            }
-        }
-
-        @Override
-        public BigDecimal next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            if (cursor == null) {
-                cursor = start;
-            } else {
-                cursor = cursor.add(increment);
-            }
-            return cursor;
-        }
-
-    }
-
     @Override
     public ASTNode[] getChildrenNode() {
-        ASTNode[] children = new ASTNode[ iterationContexts.size() + 1 ];
+        ASTNode[] children = new ASTNode[iterationContexts.size() + 1];
         System.arraycopy(iterationContexts.toArray(new ASTNode[]{}), 0, 
children, 0, iterationContexts.size());
-        children[ children.length-1 ] = expression;
+        children[children.length - 1] = expression;
         return children;
     }
 
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIterator.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIterator.java
new file mode 100644
index 0000000000..3e58ff35f5
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIterator.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public class BigDecimalRangeIterator implements Iterator<BigDecimal> {
+
+    private final BigDecimal start;
+    private final BigDecimal end;
+
+    private BigDecimal cursor;
+    private final Direction direction;
+    private final BigDecimal increment;
+
+    public BigDecimalRangeIterator(BigDecimal start, BigDecimal end) {
+        this.start = start;
+        this.end = end;
+        this.direction = (start.compareTo(end) <= 0) ? Direction.ASCENDANT : 
Direction.DESCENDANT;
+        this.increment = (direction == Direction.ASCENDANT) ? new 
BigDecimal(1, MathContext.DECIMAL128) : new BigDecimal(-1, 
MathContext.DECIMAL128);
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (cursor == null) {
+            return true;
+        } else {
+            BigDecimal lookAhead = cursor.add(increment);
+            if (direction == Direction.ASCENDANT) {
+                return lookAhead.compareTo(end) <= 0;
+            } else {
+                return lookAhead.compareTo(end) >= 0;
+            }
+        }
+    }
+
+    @Override
+    public BigDecimal next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        if (cursor == null) {
+            cursor = start;
+        } else {
+            cursor = cursor.add(increment);
+        }
+        return cursor;
+    }
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/Direction.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/Direction.java
new file mode 100644
index 0000000000..035a5fc985
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/Direction.java
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+enum Direction {
+    ASCENDANT,
+    DESCENDANT;
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
new file mode 100644
index 0000000000..43f4f576c0
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Iterator;
+import java.util.function.Supplier;
+
+public class ForIteration {
+    private String name;
+    private Iterable values;
+
+    private Supplier<Iterator> iteratorGenerator;
+    private Iterator iterator;
+
+    public ForIteration(String name, Iterable values) {
+        this.name = name;
+        this.values = values;
+        this.iteratorGenerator = () -> this.values.iterator();
+    }
+
+    public ForIteration(String name, final BigDecimal start, final BigDecimal 
end) {
+        this.name = name;
+        this.iteratorGenerator = () -> new BigDecimalRangeIterator(start, end);
+    }
+
+    public ForIteration(String name, final LocalDate start, final LocalDate 
end) {
+        this.name = name;
+        this.iteratorGenerator = () -> new LocalDateRangeIterator(start, end);
+    }
+
+    public boolean hasNextValue() {
+        if (iterator == null) {
+            iterator = iteratorGenerator.get();
+        }
+        boolean hasValue = this.iterator.hasNext();
+        if (!hasValue) {
+            this.iterator = null;
+        }
+        return hasValue;
+    }
+
+    public Object getNextValue() {
+        return iterator != null ? iterator.next() : null;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtils.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtils.java
new file mode 100644
index 0000000000..2e02c5df99
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtils.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeNotValidTypeException;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeOfDifferentTypeException;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.runtime.events.ASTEventBase;
+import org.kie.dmn.feel.util.Msg;
+
+public class ForIterationUtils {
+
+    private ForIterationUtils() {
+    }
+
+    public static ForIteration getForIteration(EvaluationContext ctx, String 
name, Object start, Object end) {
+        validateValues(ctx, start, end);
+        if (start instanceof BigDecimal bigDecimal) {
+            return new ForIteration(name, bigDecimal, (BigDecimal) end);
+        }
+        if (start instanceof LocalDate localDate) {
+            return new ForIteration(name, localDate, (LocalDate) end);
+        }
+        ctx.notifyEvt(() -> new ASTEventBase(FEELEvent.Severity.ERROR,
+                                             
Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER_NOT_A_DATE,
 start), null));
+        throw new EndpointOfRangeOfDifferentTypeException();
+    }
+
+    static void validateValues(EvaluationContext ctx, Object start, Object 
end) {
+        if (start.getClass() != end.getClass()) {
+            ctx.notifyEvt(() -> new ASTEventBase(FEELEvent.Severity.ERROR,
+                    Msg.createMessage(Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, 
start, end), null));
+            throw new EndpointOfRangeOfDifferentTypeException();
+        }
+        valueMustBeValid(ctx, start);
+        valueMustBeValid(ctx, end);
+    }
+
+    static void valueMustBeValid(EvaluationContext ctx, Object value) {
+        if (!(value instanceof BigDecimal) && !(value instanceof LocalDate)) {
+            ctx.notifyEvt(() -> new ASTEventBase(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER_NOT_A_DATE,
 value), null));
+            throw new EndpointOfRangeNotValidTypeException();
+        }
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIterator.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIterator.java
new file mode 100644
index 0000000000..a7f4ee5e28
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIterator.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import java.time.LocalDate;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public class LocalDateRangeIterator implements Iterator<LocalDate> {
+    private final LocalDate start;
+    private final LocalDate end;
+
+    private LocalDate cursor;
+    private final Direction direction;
+    private final int increment;
+
+    public LocalDateRangeIterator(LocalDate start, LocalDate end) {
+        this.start = start;
+        this.end = end;
+        this.direction = (!start.isAfter(end)) ? Direction.ASCENDANT : 
Direction.DESCENDANT;
+        this.increment = (direction == Direction.ASCENDANT) ? 1 : -1;
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (cursor == null) {
+            return true;
+        } else {
+            LocalDate lookAhead = cursor.plusDays(increment);
+            if (direction == Direction.ASCENDANT) {
+                return !lookAhead.isAfter(end);
+            } else {
+                return !lookAhead.isBefore(end);
+            }
+        }
+    }
+
+    @Override
+    public LocalDate next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        if (cursor == null) {
+            cursor = start;
+        } else {
+            cursor = cursor.plusDays(increment);
+        }
+        return cursor;
+    }
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIterator.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIterator.java
new file mode 100644
index 0000000000..49292c6f36
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIterator.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import java.time.ZonedDateTime;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public class ZonedDateTimeRangeIterator implements Iterator<ZonedDateTime> {
+
+    private final ZonedDateTime start;
+    private final ZonedDateTime end;
+
+    private ZonedDateTime cursor;
+    private final Direction direction;
+    private final int increment;
+
+    public ZonedDateTimeRangeIterator(ZonedDateTime start, ZonedDateTime end) {
+        // datetime
+        this.start = start;
+        this.end = end;
+        this.direction = (!start.isAfter(end)) ? Direction.ASCENDANT : 
Direction.DESCENDANT;
+        this.increment = (direction == Direction.ASCENDANT) ? 1 : -1;
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (cursor == null) {
+            return true;
+        } else {
+            ZonedDateTime lookAhead = cursor.plusDays(increment);
+            if (direction == Direction.ASCENDANT) {
+                return !lookAhead.isAfter(end);
+            } else {
+                return !lookAhead.isBefore(end);
+            }
+        }
+    }
+
+    @Override
+    public ZonedDateTime next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        if (cursor == null) {
+            cursor = start;
+        } else {
+            cursor = cursor.plusDays(increment);
+        }
+        return cursor;
+    }
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
index 3b3e6d348f..9f4a632462 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
 import java.math.MathContext;
 import java.time.Duration;
 import java.time.LocalDate;
+import java.time.Period;
 import java.time.chrono.ChronoPeriod;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAmount;
@@ -39,6 +40,10 @@ public class AddExecutor implements InfixExecutor {
 
     private static final AddExecutor INSTANCE = new AddExecutor();
 
+    private AddExecutor() {
+        // Singleton pattern
+    }
+
     public static AddExecutor instance() {
         return INSTANCE;
     }
@@ -65,35 +70,38 @@ public class AddExecutor implements InfixExecutor {
                     null;
         }
 
-        if (left instanceof String) {
-            return right instanceof String ? left + (String) right : null;
+        if (left instanceof String stringLeft) {
+            return right instanceof String stringRight ? stringLeft + 
stringRight : null;
         }
 
-        if (left instanceof Duration) {
-            if (right instanceof LocalDate) {
-                return addLocalDateAndDuration((LocalDate) right, (Duration) 
left);
+        if (left instanceof Duration leftDuration) {
+            if (right instanceof LocalDate localDate) {
+                return addLocalDateAndDuration(localDate, leftDuration);
             }
-            if (right instanceof Duration) {
-                return ((Duration) left).plus((Duration) right);
+            if (right instanceof Duration rightDuration) {
+                return leftDuration.plus(rightDuration);
             }
         }
-        if (right instanceof Duration && left instanceof LocalDate) {
-            return addLocalDateAndDuration((LocalDate) left, (Duration) right);
+        if (right instanceof Duration duration && left instanceof LocalDate 
localDate) {
+            return addLocalDateAndDuration(localDate, duration);
         }
 
-        if (left instanceof Temporal) {
-            if (right instanceof TemporalAmount) {
-                return ((Temporal) left).plus((TemporalAmount) right);
+        if (left instanceof Temporal temporal) {
+            if (right instanceof TemporalAmount temporalAmount) {
+                return temporal.plus(temporalAmount);
             }
-        } else if (left instanceof TemporalAmount) {
-            if (right instanceof Temporal) {
-                return ((Temporal) right).plus((TemporalAmount) left);
+            if (right instanceof BigDecimal bigDecimal) {
+                Period toAdd = Period.ofDays(bigDecimal.intValue());
+                return temporal.plus(toAdd);
             }
-            if (right instanceof ChronoPeriod) {
-                return ((ChronoPeriod) right).plus((TemporalAmount) left);
+        } else if (left instanceof TemporalAmount temporalAmount) {
+            if (right instanceof Temporal temporal) {
+                return temporal.plus(temporalAmount);
+            }
+            if (right instanceof ChronoPeriod chronoPeriod) {
+                return chronoPeriod.plus(temporalAmount);
             }
         }
-
         ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
         return null;
     }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
index 766c74ba65..01bc99c19c 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
@@ -6,9 +6,9 @@
  * to you 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *   http://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
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
index 8c079bd9c9..832e472b64 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
@@ -6,9 +6,9 @@
  * to you 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *   http://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
diff --git a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/Msg.java 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/Msg.java
index 3630110d43..1eb8b5a01d 100644
--- a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/Msg.java
+++ b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/Msg.java
@@ -38,7 +38,7 @@ public final class Msg {
     public static final Message2 INDEX_OUT_OF_BOUND = new Message2("Index out 
of bound: list of %s elements, index %s; will evaluate as FEEL null");
     public static final Message2 X_TYPE_INCOMPATIBLE_WITH_Y_TYPE = new 
Message2("%s type incompatible with %s type");
     public static final Message1 INCOMPATIBLE_TYPE_FOR_RANGE = new 
Message1("Type %s can not be used in a range unary test");
-    public static final Message1 
VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER = new 
Message1("Value %s is not a valid endpoint for range, because not a 
feel:number");
+    public static final Message1 
VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER_NOT_A_DATE = new 
Message1("Value %s is not a valid endpoint for range, because neither a 
feel:number nor a feel:date");
     public static final Message1 EVALUATED_TO_NULL = new Message1("%s 
evaluated to null");
     public static final Message1 IS_NULL = new Message1("%s is null");
     public static final Message0 BASE_NODE_EVALUATE_CALLED = new 
Message0("BaseNode evaluate called");
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIteratorTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIteratorTest.java
new file mode 100644
index 0000000000..cffdd4615f
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/BigDecimalRangeIteratorTest.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class BigDecimalRangeIteratorTest {
+
+    @Test
+    public void hasNextAscendantTest() {
+        BigDecimal start = BigDecimal.valueOf(1);
+        BigDecimal end = BigDecimal.valueOf(3);
+        BigDecimalRangeIterator iterator = new BigDecimalRangeIterator(start, 
end);
+        assertTrue(iterator.hasNext());
+        BigDecimal next = iterator.next();
+        while (!next.equals(end)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void hasNextDescendantTest() {
+        BigDecimal start = BigDecimal.valueOf(3);
+        BigDecimal end = BigDecimal.valueOf(1);
+        BigDecimalRangeIterator iterator = new BigDecimalRangeIterator(start, 
end);
+        assertTrue(iterator.hasNext());
+        BigDecimal next = iterator.next();
+        while (!next.equals(end)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void nextAscendantTest() {
+        BigDecimal start = BigDecimal.valueOf(1);
+        BigDecimal end = BigDecimal.valueOf(3);
+        List<BigDecimal> expected = Arrays.asList(BigDecimal.valueOf(1), 
BigDecimal.valueOf(2), BigDecimal.valueOf(3));
+        BigDecimalRangeIterator iterator = new BigDecimalRangeIterator(start, 
end);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+    @Test
+    public void nextDescendantTest() {
+        BigDecimal start = BigDecimal.valueOf(3);
+        BigDecimal end = BigDecimal.valueOf(1);
+        List<BigDecimal> expected = Arrays.asList(BigDecimal.valueOf(3), 
BigDecimal.valueOf(2), BigDecimal.valueOf(1));
+        BigDecimalRangeIterator iterator = new BigDecimalRangeIterator(start, 
end);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationTest.java
new file mode 100644
index 0000000000..56512a3c42
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationTest.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+
+public class ForIterationTest {
+
+    @Test
+    public void hasNextValueBigDecimalTest() {
+        BigDecimal start = BigDecimal.valueOf(1);
+        BigDecimal end = BigDecimal.valueOf(3);
+        ForIteration iteration = new ForIteration("iteration", start, end);
+        assertTrue(iteration.hasNextValue());
+        BigDecimal next = (BigDecimal) iteration.getNextValue();
+        while (!next.equals(end)) {
+            assertTrue(iteration.hasNextValue());
+            next = (BigDecimal) iteration.getNextValue();
+        }
+        assertFalse(iteration.hasNextValue());
+    }
+
+    @Test
+    public void hasNextValueLocalDateTest() {
+        LocalDate start = LocalDate.of(2021, 1, 1);
+        LocalDate end = LocalDate.of(2021, 1, 3);
+        ForIteration iteration = new ForIteration("iteration", start, end);
+        assertTrue(iteration.hasNextValue());
+        LocalDate next = (LocalDate) iteration.getNextValue();
+        while (!next.equals(end)) {
+            assertTrue(iteration.hasNextValue());
+            next = (LocalDate) iteration.getNextValue();
+        }
+        assertFalse(iteration.hasNextValue());
+    }
+
+    @Test
+    public void getNextValueBigDecimalTest() {
+        BigDecimal start = BigDecimal.valueOf(1);
+        BigDecimal end = BigDecimal.valueOf(3);
+        List<BigDecimal> expected = Arrays.asList(BigDecimal.valueOf(1), 
BigDecimal.valueOf(2), BigDecimal.valueOf(3));
+        ForIteration iteration = new ForIteration("iteration", start, end);
+        iteration.hasNextValue();
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iteration.getNextValue()));
+    }
+
+    @Test
+    public void getNextValueLocalDateTest() {
+        LocalDate start = LocalDate.of(2021, 1, 3);
+        LocalDate end = LocalDate.of(2021, 1, 1);
+        List<LocalDate> expected = Arrays.asList(LocalDate.of(2021, 1, 3), 
LocalDate.of(2021, 1, 2), LocalDate.of(2021, 1, 1));
+        ForIteration iteration = new ForIteration("iteration", start, end);
+        iteration.hasNextValue();
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iteration.getNextValue()));
+    }
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtilsTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtilsTest.java
new file mode 100644
index 0000000000..bb50aca414
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIterationUtilsTest.java
@@ -0,0 +1,154 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.api.feel.runtime.events.FEELEventListener;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeNotValidTypeException;
+import org.kie.dmn.feel.exceptions.EndpointOfRangeOfDifferentTypeException;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.impl.FEELEventListenersManager;
+import org.mockito.ArgumentCaptor;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static 
org.kie.dmn.feel.codegen.feel11.CodegenTestUtil.newEmptyEvaluationContext;
+import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils.getForIteration;
+import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils.validateValues;
+import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils.valueMustBeValid;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class ForIterationUtilsTest {
+
+    private FEELEventListener listener;
+    private EvaluationContext ctx;
+
+    @Before
+    public void setup() {
+        final FEELEventListenersManager mngr = new FEELEventListenersManager();
+        listener = mock(FEELEventListener.class);
+        mngr.addListener(listener);
+        ctx = newEmptyEvaluationContext(mngr);
+    }
+
+    @Test
+    public void getForIterationValidTest() {
+        ForIteration retrieved = getForIteration(ctx, "iteration", 
BigDecimal.valueOf(1), BigDecimal.valueOf(3));
+        assertNotNull(retrieved);
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+        retrieved = getForIteration(ctx, "iteration", LocalDate.of(2021, 1, 
1), LocalDate.of(2021, 1, 3));
+        assertNotNull(retrieved);
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+    }
+
+    @Test
+    public void getForIterationNotValidTest() {
+        try {
+            getForIteration(ctx, "iteration", "NOT", "VALID");
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeNotValidTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+        try {
+            getForIteration(ctx, "iteration", BigDecimal.valueOf(1), 
LocalDate.of(2021, 1, 1));
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeOfDifferentTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+        try {
+            getForIteration(ctx, "iteration", LocalDate.of(2021, 1, 1), 
BigDecimal.valueOf(1));
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeOfDifferentTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+    }
+
+    @Test
+    public void valueMustBeValidTrueTest() {
+        valueMustBeValid(ctx, BigDecimal.valueOf(1));
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+        valueMustBeValid(ctx, LocalDate.of(2021, 1, 3));
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+    }
+
+    @Test
+    public void valueMustBeValidFalseTest() {
+        try {
+            valueMustBeValid(ctx, "INVALID");
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeNotValidTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+        }
+    }
+
+    @Test
+    public void validateValuesTrueTest() {
+        validateValues(ctx, BigDecimal.valueOf(1), BigDecimal.valueOf(3));
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+        validateValues(ctx, LocalDate.of(2021, 1, 1), LocalDate.of(2021, 1, 
3));
+        verify(listener, never()).onEvent(any(FEELEvent.class));
+    }
+
+    @Test
+    public void validateValuesFalseTest() {
+        try {
+            validateValues(ctx, "INVALID", "INVALID");
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeNotValidTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+        try {
+            validateValues(ctx, BigDecimal.valueOf(1), LocalDate.of(2021, 1, 
1));
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeOfDifferentTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+        try {
+            validateValues(ctx, LocalDate.of(2021, 1, 1), 
BigDecimal.valueOf(1));
+        } catch (Exception e) {
+            assertTrue(e instanceof EndpointOfRangeOfDifferentTypeException);
+            final ArgumentCaptor<FEELEvent> captor = 
ArgumentCaptor.forClass(FEELEvent.class);
+            verify(listener, times(1)).onEvent(captor.capture());
+            reset(listener);
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIteratorTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIteratorTest.java
new file mode 100644
index 0000000000..6c40c0813f
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/LocalDateRangeIteratorTest.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *   http://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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class LocalDateRangeIteratorTest {
+
+    private static LocalDate before;
+    private static LocalDate after;
+
+    @BeforeClass
+    public static void setup() {
+        before = LocalDate.of(2021, 1, 1);
+        after = LocalDate.of(2021, 1, 3);
+    }
+
+    @Test
+    public void hasNextAscendantTest() {
+        LocalDateRangeIterator iterator = new LocalDateRangeIterator(before, 
after);
+        assertTrue(iterator.hasNext());
+        LocalDate next = iterator.next();
+        while (!next.equals(after)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void hasNextDescendantTest() {
+        LocalDateRangeIterator iterator = new LocalDateRangeIterator(after, 
before);
+        assertTrue(iterator.hasNext());
+        LocalDate next = iterator.next();
+        while (!next.equals(before)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void nextAscendantTest() {
+        List<LocalDate> expected = Arrays.asList(LocalDate.of(2021, 1, 1), 
LocalDate.of(2021, 1, 2), LocalDate.of(2021, 1, 3));
+        LocalDateRangeIterator iterator = new LocalDateRangeIterator(before, 
after);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+    @Test
+    public void nextDescendantTest() {
+        List<LocalDate> expected = Arrays.asList(LocalDate.of(2021, 1, 3), 
LocalDate.of(2021, 1, 2), LocalDate.of(2021, 1, 1));
+        LocalDateRangeIterator iterator = new LocalDateRangeIterator(after, 
before);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIteratorTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIteratorTest.java
new file mode 100644
index 0000000000..fce2e1dda6
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ZonedDateTimeRangeIteratorTest.java
@@ -0,0 +1,115 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.kie.dmn.feel.lang.ast.forexpressioniterators;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ZonedDateTimeRangeIteratorTest {
+
+    private static ZonedDateTime before;
+    private static ZonedDateTime after;
+
+    @BeforeClass
+    public static void setup() {
+        // Tests using on those variables relies on the exact hour/minute, 
because the ZonedDateTimeRangeIterator is meant to iterate on a full-day base
+        before = getZonedDateTime(2021, 1, 1, 10, 15);
+        after = getZonedDateTime(2021, 1, 3, 10, 15);
+    }
+
+    @Test
+    public void hasNextAscendantTest() {
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(before, after);
+        assertTrue(iterator.hasNext());
+        ZonedDateTime next = iterator.next();
+        while (next.isBefore(after)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void hasNextDescendantTest() {
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(after, before);
+        assertTrue(iterator.hasNext());
+        ZonedDateTime next = iterator.next();
+        while (!next.equals(before)) {
+            assertTrue(iterator.hasNext());
+            next = iterator.next();
+        }
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void nextAscendantTest() {
+        List<ZonedDateTime> expected = Arrays.asList(getZonedDateTime(2021, 1, 
1, 10, 15),
+                getZonedDateTime(2021, 1, 2, 10, 15),
+                getZonedDateTime(2021, 1, 3, 10, 15));
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(before, after);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+    @Test
+    public void nextDescendantTest() {
+        List<ZonedDateTime> expected = Arrays.asList(getZonedDateTime(2021, 1, 
3, 10, 15),
+                getZonedDateTime(2021, 1, 2, 10, 15),
+                getZonedDateTime(2021, 1, 1, 10, 15));
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(after, before);
+        IntStream.range(0, 3).forEach(i -> assertEquals(expected.get(i), 
iterator.next()));
+    }
+
+
+    @Test
+    public void hasNotNextAscendantTest() {
+        ZonedDateTime start = getZonedDateTime(2021, 1, 1, 10, 15);
+        ZonedDateTime end = getZonedDateTime(2021, 1, 2, 10, 14);
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(start, end);
+        ZonedDateTime retrieved = iterator.next();
+        assertEquals(start, retrieved);
+        assertFalse(iterator.hasNext());
+    }
+    @Test
+    public void hasNotNextDescendantTest() {
+        ZonedDateTime start = getZonedDateTime(2021, 1, 2, 10, 14);
+        ZonedDateTime end = getZonedDateTime(2021, 1, 1, 10, 15);
+        ZonedDateTimeRangeIterator iterator = new 
ZonedDateTimeRangeIterator(start, end);
+        ZonedDateTime retrieved = iterator.next();
+        assertEquals(start, retrieved);
+        assertFalse(iterator.hasNext());
+    }
+
+    private static ZonedDateTime getZonedDateTime(int year, int month, int 
dayOfMonth, int hour, int minute) {
+        LocalDateTime startDateTime = LocalDateTime.of(year, month, 
dayOfMonth, hour, minute);
+        return ZonedDateTime.of(startDateTime, ZoneId.systemDefault());
+    }
+
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEEL12ExtendedForLoopTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEEL12ExtendedForLoopTest.java
index fb06b3174f..df581ad778 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEEL12ExtendedForLoopTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEEL12ExtendedForLoopTest.java
@@ -18,7 +18,12 @@
  */
 package org.kie.dmn.feel.runtime;
 
+import org.junit.runners.Parameterized;
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.util.EvalHelper;
+
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -26,10 +31,6 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
-import org.junit.runners.Parameterized;
-import org.kie.dmn.api.feel.runtime.events.FEELEvent;
-import org.kie.dmn.feel.util.EvalHelper;
-
 import static org.kie.dmn.feel.util.DynamicTypeUtils.entry;
 import static org.kie.dmn.feel.util.DynamicTypeUtils.mapOf;
 
@@ -38,20 +39,21 @@ public class FEEL12ExtendedForLoopTest extends BaseFEELTest 
{
     @Parameterized.Parameters(name = "{index}: {0} ({1}) = {2}")
     public static Collection<Object[]> data() {
         final Object[][] cases = new Object[][] {
-            //normal:
-            {"for x in [1, 2, 3] return x+1", Stream.of(1, 2, 3 ).map(x -> 
BigDecimal.valueOf(x + 1 ) ).collect(Collectors.toList() ), null},
-            
-            //extended:
-            {"for x in 1..3 return x+1", Stream.of(1, 2, 3 ).map(x -> 
BigDecimal.valueOf(x + 1 ) ).collect(Collectors.toList() ), null},
-            {"for x in 1..\"ciao\" return x+1", null, 
FEELEvent.Severity.ERROR},
-            {"for x in 3..1 return x+1", Stream.of(3, 2, 1 ).map(x -> 
BigDecimal.valueOf(x + 1 ) ).collect(Collectors.toList() ), null},
-            {"for x in 1..1 return x+1", Stream.of(1 ).map(x -> 
BigDecimal.valueOf(x + 1 ) ).collect(Collectors.toList() ), null},
-            {"for x in 1..3, y in 4..6 return [x+1, y-1]", l(l(2, 3), l(2, 4), 
l(2, 5), l(3, 3), l(3, 4), l(3, 5), l(4, 3), l(4, 4), l(4, 5)), null},
-            {"{ a: 1, b : 3, c : for x in a..b return x+1}", mapOf(entry("a", 
BigDecimal.valueOf(1)), entry("b", BigDecimal.valueOf(3)),  entry("c", 
Stream.of(1, 2, 3 ).map(x -> BigDecimal.valueOf(x + 1 ) 
).collect(Collectors.toList() )) ), null},
-            {"{ a: 1, b : 3, c : for x in a+2..b-2 return x+1}", 
mapOf(entry("a", BigDecimal.valueOf(1)), entry("b", BigDecimal.valueOf(3)),  
entry("c", Stream.of(3, 2, 1 ).map(x -> BigDecimal.valueOf(x + 1 ) 
).collect(Collectors.toList() )) ), null},
-            {"{ a: \"ciao\", b : 3, c : for x in a..b return x+1}", 
mapOf(entry("a", "ciao"), entry("b", BigDecimal.valueOf(3)),  entry("c", 
null)), FEELEvent.Severity.ERROR},
-            {"for i in 0..10 return if i = 0 then 1 else i * partial[-1]", 
Stream.of(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 
).map(BigDecimal::valueOf).collect(Collectors.toList() ), null},
-            {"{xs: for i in 1..10 return function() i, ys: for f in xs return 
f()}.ys", IntStream.range(1, 
11).boxed().map(BigDecimal::valueOf).collect(Collectors.toList()), null},
+          //normal:
+          {"for x in [1, 2, 3] return x+1", Stream.of(1, 2, 3 ).map(x -> 
BigDecimal.valueOf(x + 1 ) ).collect(Collectors.toList() ), null},
+          {"for x in @\"2021-01-01\"..@\"2021-01-03\" return x+1", 
Stream.of("2021-01-02", "2021-01-03", "2021-01-04" 
).map(LocalDate::parse).collect(Collectors.toList() ), null},
+
+          //extended:
+          {"for x in 1..3 return x+1", Stream.of(1, 2, 3).map(x -> 
BigDecimal.valueOf(x + 1)).collect(Collectors.toList()), null},
+          {"for x in 1..\"ciao\" return x+1", null, FEELEvent.Severity.ERROR},
+          {"for x in 3..1 return x+1", Stream.of(3, 2, 1).map(x -> 
BigDecimal.valueOf(x + 1)).collect(Collectors.toList()), null},
+          {"for x in 1..1 return x+1", Stream.of(1).map(x -> 
BigDecimal.valueOf(x + 1)).collect(Collectors.toList()), null},
+          {"for x in 1..3, y in 4..6 return [x+1, y-1]", l(l(2, 3), l(2, 4), 
l(2, 5), l(3, 3), l(3, 4), l(3, 5), l(4, 3), l(4, 4), l(4, 5)), null},
+          {"{ a: 1, b : 3, c : for x in a..b return x+1}", mapOf(entry("a", 
BigDecimal.valueOf(1)), entry("b", BigDecimal.valueOf(3)), entry("c", 
Stream.of(1, 2, 3).map(x -> BigDecimal.valueOf(x + 
1)).collect(Collectors.toList()))), null},
+          {"{ a: 1, b : 3, c : for x in a+2..b-2 return x+1}", 
mapOf(entry("a", BigDecimal.valueOf(1)), entry("b", BigDecimal.valueOf(3)), 
entry("c", Stream.of(3, 2, 1).map(x -> BigDecimal.valueOf(x + 
1)).collect(Collectors.toList()))), null},
+          {"{ a: \"ciao\", b : 3, c : for x in a..b return x+1}", 
mapOf(entry("a", "ciao"), entry("b", BigDecimal.valueOf(3)), entry("c", null)), 
FEELEvent.Severity.ERROR},
+          {"for i in 0..10 return if i = 0 then 1 else i * partial[-1]", 
Stream.of(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 
3628800).map(BigDecimal::valueOf).collect(Collectors.toList()), null},
+          {"{xs: for i in 1..10 return function() i, ys: for f in xs return 
f()}.ys", IntStream.range(1, 
11).boxed().map(BigDecimal::valueOf).collect(Collectors.toList()), null},
 
         };
         return addAdditionalParameters(cases, false);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to