Skip to content

Commit 0ba3bd8

Browse files
tarilabsetirelli
authored andcommitted
InvalidParameterEvent and listener support implementation. (apache#21)
* InvalidParameterEvent and listener support implementation. * Bad copy-paste, fix. * Using parameter annotation to determine the (FEEL spec) param name. * Refining error message by using FEELEvent as Either/Left. * InvalidParameterEvent avoid hard-coded msg in favor of i18n-friendly dynamic structure. * Extending InvalidParametersEvent support. * Extending InvalidParametersEvent support. * Extending InvalidParametersEvent support. * Extending InvalidParametersEvent support. * For BaseFEELFunction pairing slf4j log with FEELEvent based notification. * Minor corrections and minor refactorings. * Extending InvalidParametersEvent support to CustomFEELFunction. * Fixing BaseFEELFunction support for Either, minor refactorings. * Extending FEELEvent support to Java(FEEL)Function. * Extending FEELEvent support to DTInvokerFunction, small DMN-level fix. * . * Normalize BigDecimal creation for functions via EvalHelper.getBigDecimalOrNull . * Refactoring by implementing FEELFnResult<T> as an "alias" for Either<FEELEvent, T> . * Include license header to items which missed it
1 parent f748a5a commit 0ba3bd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1023
-258
lines changed

kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DecisionNode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.kie.dmn.feel.runtime.events.FEELEventListener;
3232

3333
import java.util.*;
34+
import java.util.function.Function;
3435

3536
public class DecisionNode extends DMNBaseNode implements DMNNode {
3637

@@ -147,7 +148,7 @@ public EvaluatorResult evaluate(InternalDMNRuntimeEventManager eventManager, DMN
147148
params[i] = feel.evaluate( paramNames.get( i ), result.getContext().getAll() );
148149
ctx.setValue( paramNames.get( i ), params[i] );
149150
}
150-
Object dtr = dt.apply( ctx, params );
151+
Object dtr = dt.apply( ctx, params ).cata(e -> { events.add(e); return null; }, Function.identity());
151152
r = processEvents( events, eventManager, result );
152153
return new EvaluatorResult( dtr, r.hasErrors ? ResultType.FAILURE : ResultType.SUCCESS );
153154
} finally {

kie-dmn-core/src/main/java/org/kie/dmn/core/impl/FeelTypeImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,13 @@ public void setAllowedValues(List<?> allowedValues) {
8383

8484
@Override
8585
public Object parseValue(String value) {
86+
// TODO we should add the EventListener here somehow?
8687
return feelType.fromString( value );
8788
}
8889

8990
@Override
9091
public String toString(Object value) {
92+
// TODO we should add the EventListener here somehow?
9193
return feelType.toString( value );
9294
}
9395

kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/FEELProperty.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package org.kie.dmn.feel.lang;
218

319
import static java.lang.annotation.RetentionPolicy.RUNTIME;

kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/FEELType.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package org.kie.dmn.feel.lang;
218

319
import static java.lang.annotation.ElementType.TYPE;
@@ -6,7 +22,6 @@
622
import java.lang.annotation.Retention;
723
import java.lang.annotation.Target;
824

9-
1025
@Retention(RUNTIME)
1126
@Target(TYPE)
1227
public @interface FEELType {

kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/Type.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ public interface Type {
2020

2121
String getName();
2222

23+
// TODO possibly to separate in a marshaller
2324
Object fromString( String value );
2425

26+
// TODO possibly to separate in a marshaller
2527
String toString( Object value );
2628

2729
}

kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/types/BuiltInType.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
import org.kie.dmn.feel.runtime.FEELFunction;
2323
import org.kie.dmn.feel.runtime.Range;
2424
import org.kie.dmn.feel.runtime.UnaryTest;
25+
import org.kie.dmn.feel.runtime.events.FEELEvent;
2526
import org.kie.dmn.feel.runtime.functions.*;
2627

2728
import java.math.BigDecimal;
2829
import java.time.*;
2930
import java.util.List;
3031
import java.util.Map;
32+
import java.util.function.Function;
3133

3234
public enum BuiltInType implements Type {
3335

@@ -60,12 +62,12 @@ public String getName() {
6062
@Override
6163
public Object fromString(String value) {
6264
switch ( this ) {
63-
case NUMBER: return BuiltInFunctions.getFunction( NumberFunction.class).apply( value, null, null );
65+
case NUMBER: return BuiltInFunctions.getFunction( NumberFunction.class).apply( value, null, null ).cata(BuiltInType.justNull(), Function.identity());
6466
case STRING: return value;
65-
case DATE: return BuiltInFunctions.getFunction( DateFunction.class ).apply( value );
66-
case TIME: return BuiltInFunctions.getFunction( TimeFunction.class ).apply( value );
67-
case DATE_TIME: return BuiltInFunctions.getFunction( DateTimeFunction.class ).apply( value );
68-
case DURATION: return BuiltInFunctions.getFunction( DurationFunction.class ).apply( value );
67+
case DATE: return BuiltInFunctions.getFunction( DateFunction.class ).apply( value ).cata(BuiltInType.justNull(), Function.identity());
68+
case TIME: return BuiltInFunctions.getFunction( TimeFunction.class ).apply( value ).cata(BuiltInType.justNull(), Function.identity());
69+
case DATE_TIME: return BuiltInFunctions.getFunction( DateTimeFunction.class ).apply( value ).cata(BuiltInType.justNull(), Function.identity());
70+
case DURATION: return BuiltInFunctions.getFunction( DurationFunction.class ).apply( value ).cata(BuiltInType.justNull(), Function.identity());
6971
case BOOLEAN: return Boolean.parseBoolean( value );
7072
case RANGE:
7173
case FUNCTION:
@@ -79,7 +81,12 @@ public Object fromString(String value) {
7981

8082
@Override
8183
public String toString(Object value) {
82-
return BuiltInFunctions.getFunction( StringFunction.class ).apply( value );
84+
return BuiltInFunctions.getFunction( StringFunction.class ).apply( value ).cata(BuiltInType.justNull(), Function.identity());
85+
}
86+
87+
static <T> Function<FEELEvent, T> justNull() {
88+
// TODO we should add the EventListener here somehow?
89+
return t -> null;
8390
}
8491

8592
public Symbol getSymbol() { return symbol; }

kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/decisiontables/DecisionTableImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public Object evaluate(EvaluationContext ctx, Object[] params) {
8888
return null;
8989
}
9090
} catch ( Exception e ) {
91-
logger.error( "Error invoking decision table '" + getName() + "'.", e );
91+
// no longer needed as DTInvokerFunction support Either for wrapping the exception : logger.error( "Error invoking decision table '" + getName() + "'.", e );
9292
throw e;
9393
}
9494
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.kie.dmn.feel.runtime.events;
18+
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.Collections;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Map.Entry;
26+
import java.util.stream.Collectors;
27+
import java.util.stream.IntStream;
28+
29+
/**
30+
* An event class to report an evaluation error occured due to invalid parameters.
31+
*/
32+
public class InvalidParametersEvent
33+
extends FEELEventBase
34+
implements FEELEvent {
35+
36+
private String genericProblem;
37+
private String paramNameInError;
38+
private String paramProblem;
39+
private String nodeName;
40+
private final Map<String, Object> actualParameters = new HashMap<>();
41+
42+
public InvalidParametersEvent(Severity severity, String genericProblem) {
43+
super( severity, null, null );
44+
this.genericProblem = genericProblem;
45+
}
46+
47+
public InvalidParametersEvent(Severity severity, String genericProblem, Throwable sourceException ) {
48+
super( severity, null, sourceException );
49+
this.genericProblem = genericProblem;
50+
}
51+
52+
public InvalidParametersEvent(Severity severity, String paramNameInError, String paramProblem) {
53+
super( severity, null, null );
54+
this.paramNameInError = paramNameInError;
55+
this.paramProblem = paramProblem;
56+
}
57+
58+
public InvalidParametersEvent(Severity severity, String paramNameInError, String paramProblem, Throwable sourceException ) {
59+
super( severity, null, sourceException );
60+
this.paramNameInError = paramNameInError;
61+
this.paramProblem = paramProblem;
62+
}
63+
64+
@Override
65+
public String getMessage() {
66+
if (genericProblem == null ) {
67+
return "The parameter '"+paramNameInError+"', in function "+getNodeName()+"(), "+paramProblem+".";
68+
} else {
69+
return genericProblem;
70+
}
71+
}
72+
73+
public void setNodeName(String nodeName) {
74+
this.nodeName = nodeName;
75+
}
76+
77+
public String getNodeName() {
78+
return nodeName;
79+
}
80+
81+
public void setActualParameters(List<String> parameterNames, List<Object> parameterValues) {
82+
this.actualParameters.clear();
83+
IntStream.range(0, parameterNames.size())
84+
.forEach( idx -> actualParameters.put(parameterNames.get(idx), parameterValues.get(idx)) );
85+
}
86+
87+
public Map<String, Object> getActualParameters() {
88+
return Collections.unmodifiableMap( actualParameters );
89+
}
90+
91+
@Override
92+
public String toString() {
93+
StringBuilder builder = new StringBuilder();
94+
builder.append("InvalidParametersEvent{")
95+
.append("getSeverity()=").append(getSeverity())
96+
.append(", nodeName=").append(nodeName)
97+
.append(", message=").append(getMessage())
98+
.append(", actualParameters=").append(formatMap(actualParameters))
99+
.append(", paramNameInError=").append(paramNameInError)
100+
.append(", paramProblem=").append(paramProblem)
101+
.append(", getSourceException()=").append(getSourceException())
102+
.append("}");
103+
return builder.toString();
104+
}
105+
106+
private String formatMap(Map<String, Object> actualParameters) {
107+
try {
108+
StringBuilder sb = new StringBuilder("{");
109+
sb.append(
110+
actualParameters.entrySet().stream()
111+
.map(kv -> kv.getKey() + "=" + ( kv.getValue() != null && kv.getValue().getClass().isArray() ? Arrays.deepToString( (Object[]) kv.getValue() ) : kv.getValue() ) )
112+
.collect(Collectors.joining(", "))
113+
);
114+
sb.append("}");
115+
return sb.toString();
116+
} catch (Exception e) {
117+
e.printStackTrace();
118+
return "<unable to inspect actualParameters map>";
119+
}
120+
}
121+
}

kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/AppendFunction.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,30 @@
2020
import java.util.List;
2121
import java.util.stream.Stream;
2222

23+
import org.kie.dmn.feel.lang.impl.FEELEventListenersManager;
24+
import org.kie.dmn.feel.runtime.events.InvalidInputEvent;
25+
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
26+
import org.kie.dmn.feel.runtime.functions.FEELFnResult;
27+
import org.kie.dmn.feel.runtime.events.FEELEvent;
28+
import org.kie.dmn.feel.runtime.events.FEELEvent.Severity;
29+
2330
public class AppendFunction
2431
extends BaseFEELFunction {
2532

2633
public AppendFunction() {
2734
super( "append" );
2835
}
2936

30-
public List apply( @ParameterName( "list" ) List list, @ParameterName( "item" ) Object[] items ) {
31-
if ( list == null || items == null ) {
32-
return null;
37+
public FEELFnResult<List> apply( @ParameterName( "list" ) List list, @ParameterName( "item" ) Object[] items ) {
38+
if ( list == null ) {
39+
return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "list", "cannot be null"));
40+
}
41+
if ( items == null ) {
42+
return FEELFnResult.ofError(new InvalidParametersEvent(Severity.ERROR, "item", "cannot be null"));
3343
}
3444
// spec requires us to return a new list
3545
List result = new ArrayList( list );
3646
Stream.of( items ).forEach( i -> result.add( i ) );
37-
return result;
47+
return FEELFnResult.ofResult( result );
3848
}
3949
}

0 commit comments

Comments
 (0)