Skip to content

Commit

Permalink
Adding support for BKM and refactoring expression evaluator
Browse files Browse the repository at this point in the history
  • Loading branch information
etirelli committed Dec 2, 2016
1 parent 13a660f commit 3e4d8eb
Show file tree
Hide file tree
Showing 14 changed files with 725 additions and 307 deletions.
Expand Up @@ -16,6 +16,7 @@

package org.kie.dmn.core.api;

import org.kie.dmn.core.ast.BusinessKnowledgeModelNode;
import org.kie.dmn.core.ast.DecisionNode;
import org.kie.dmn.core.ast.InputDataNode;
import org.kie.dmn.core.ast.ItemDefNode;
Expand Down Expand Up @@ -48,7 +49,17 @@ public interface DMNModel {

Set<InputDataNode> getRequiredInputsForDecisionName(String decisionName );

Set<InputDataNode> getRequiredInputsForDecisionId( String decisionName );
Set<InputDataNode> getRequiredInputsForDecisionId( String decisionId );

BusinessKnowledgeModelNode getBusinessKnowledgeModelById(String id);

BusinessKnowledgeModelNode getBusinessKnowledgeModelByName(String name);

Set<BusinessKnowledgeModelNode> getBusinessKnowledgeModels();

Set<InputDataNode> getRequiredInputsForBusinessKnowledgeModelName(String bkmName );

Set<InputDataNode> getRequiredInputsForBusinessKnowledgeModelId( String bkmId );

ItemDefNode getItemDefinitionById(String id);

Expand Down
@@ -0,0 +1,59 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.core.ast;

import org.kie.dmn.core.api.DMNType;
import org.kie.dmn.feel.model.v1_1.BusinessKnowledgeModel;

public class BusinessKnowledgeModelNode
extends DMNBaseNode
implements DMNNode {

private BusinessKnowledgeModel bkm;
private DMNExpressionEvaluator evaluator;
private DMNType resultType;

public BusinessKnowledgeModelNode() {
}

public BusinessKnowledgeModelNode(BusinessKnowledgeModel bkm, DMNType resultType) {
super( bkm );
this.bkm = bkm;
this.resultType = resultType;
}

public BusinessKnowledgeModel getBusinessKnowledModel() {
return bkm;
}

public void setBusinessKnowledgeModel(BusinessKnowledgeModel bkm) {
this.bkm = bkm;
}

public DMNExpressionEvaluator getEvaluator() {
return evaluator;
}

public void setEvaluator(DMNExpressionEvaluator evaluator) {
this.evaluator = evaluator;
}

public DMNType getResultType() {
return resultType;
}

}
Expand Up @@ -16,11 +16,21 @@

package org.kie.dmn.core.ast;

import org.kie.dmn.feel.model.v1_1.Decision;
import org.kie.dmn.feel.model.v1_1.InformationRequirement;
import org.kie.dmn.feel.model.v1_1.NamedElement;

public abstract class DMNBaseNode {
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public abstract class DMNBaseNode
implements DMNNode {

private NamedElement source;
// need to retain dependencies order, so need to use LinkedHashMap
private Map<String, DMNNode> dependencies = new LinkedHashMap<>();

public DMNBaseNode() {
}
Expand All @@ -37,4 +47,24 @@ public String getName() {
return source != null ? source.getName() : null;
}

public Map<String, DMNNode> getDependencies() {
return dependencies;
}

public void setDependencies(Map<String, DMNNode> dependencies) {
this.dependencies = dependencies;
}

public void addDependency(String name, DMNNode dependency) {
this.dependencies.put( name, dependency );
}

public List<InformationRequirement> getInformationRequirement() {
if ( source instanceof Decision ) {
return ((Decision) source).getInformationRequirement();
} else {
return Collections.emptyList();
}
}

}
@@ -0,0 +1,97 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.core.ast;

import org.kie.dmn.core.api.DMNMessage;
import org.kie.dmn.core.api.event.InternalDMNRuntimeEventManager;
import org.kie.dmn.core.impl.DMNResultImpl;
import org.kie.dmn.feel.FEEL;
import org.kie.dmn.feel.lang.impl.EvaluationContextImpl;
import org.kie.dmn.feel.lang.impl.FEELImpl;
import org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent;
import org.kie.dmn.feel.runtime.events.FEELEvent;
import org.kie.dmn.feel.runtime.events.FEELEventListener;
import org.kie.dmn.feel.runtime.functions.DTInvokerFunction;

import java.util.ArrayList;
import java.util.List;

/**
* An evaluator for DMN Decision Table Expressions
*/
public class DMNDTExpressionEvaluator
implements DMNExpressionEvaluator, FEELEventListener {
private final DMNNode node;
private DTInvokerFunction dt;
private FEELImpl feel;

private List<FEELEvent> events = new ArrayList<>();

public DMNDTExpressionEvaluator(DMNNode node, DTInvokerFunction dt) {
this.node = node;
this.dt = dt;
feel = (FEELImpl) FEEL.newInstance();
feel.addListener( this );
}

@Override
public EvaluatorResult evaluate(InternalDMNRuntimeEventManager eventManager, DMNResultImpl result) {
EventResults r = null;
try {
eventManager.fireBeforeEvaluateDecisionTable( dt.getName(), result );
List<String> paramNames = dt.getParameterNames().get( 0 );
Object[] params = new Object[paramNames.size()];
EvaluationContextImpl ctx = new EvaluationContextImpl( feel.getEventsManager() );
for ( int i = 0; i < params.length; i++ ) {
params[i] = feel.evaluate( paramNames.get( i ), result.getContext().getAll() );
ctx.setValue( paramNames.get( i ), params[i] );
}
Object dtr = dt.apply( ctx, params );
r = processEvents( events, eventManager, result );
return new EvaluatorResult( dtr, r.hasErrors ? ResultType.FAILURE : ResultType.SUCCESS );
} finally {
eventManager.fireAfterEvaluateDecisionTable( dt.getName(), result, (r != null ? r.matchedRules : null) );
}
}

private EventResults processEvents(List<FEELEvent> events, InternalDMNRuntimeEventManager eventManager, DMNResultImpl result) {
EventResults r = new EventResults();
for ( FEELEvent e : events ) {
if ( e instanceof DecisionTableRulesMatchedEvent ) {
r.matchedRules = ((DecisionTableRulesMatchedEvent) e).getMatches();
} else if ( e.getSeverity() == FEELEvent.Severity.ERROR ) {
result.addMessage( DMNMessage.Severity.ERROR, e.getMessage(), node.getId(), e );
r.hasErrors = true;
}
}
events.clear();
if ( r.matchedRules.isEmpty() ) {
r.hasErrors = true;
}
return r;
}

private static class EventResults {
public boolean hasErrors = false;
public List<Integer> matchedRules;
}

@Override
public void onEvent(FEELEvent event) {
this.events.add( event );
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.core.ast;

import org.kie.dmn.core.api.event.InternalDMNRuntimeEventManager;
import org.kie.dmn.core.impl.DMNResultImpl;

/**
* An Expression Evaluator interface for DMN defined expressions
*/
public interface DMNExpressionEvaluator {
/**
* Evaluates the expression, returning its result type (SUCCESS/FAILURE) and
* result value.
*
* @param eventManager events manager to whom events are notified
* @param result the result context instance
*
* @return the result of the evaluation of the expression
*/
EvaluatorResult evaluate(InternalDMNRuntimeEventManager eventManager, DMNResultImpl result);

enum ResultType {
SUCCESS, FAILURE;
}

class EvaluatorResult {
private final Object result;
private final ResultType code;

public EvaluatorResult(Object result, ResultType code) {
this.result = result;
this.code = code;
}

public Object getResult() {
return result;
}

public ResultType getResultType() {
return code;
}
}
}

0 comments on commit 3e4d8eb

Please sign in to comment.