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]