Skip to content

Commit

Permalink
[incubator-kie-issues-1146] Add support for transformations in input/…
Browse files Browse the repository at this point in the history
…output in activities (#3494)
  • Loading branch information
elguardian authored May 28, 2024
1 parent cc84426 commit 534f7dc
Show file tree
Hide file tree
Showing 15 changed files with 502 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ protected DataDefinition getVariableDataSpec(Parser parser, String propertyIdRef
return null;
}
Variable variable = var.get();
return new DataDefinition(variable.getId(), variable.getName(), variable.getType().getStringType());
return new DataDefinition(variable.getId(), variable.getName(), variable);
}

protected ItemDefinition getStructureRef(Parser parser, String id) {
Expand Down Expand Up @@ -630,10 +630,9 @@ private String cleanUp(String expression) {
}

private DataDefinition toDataExpression(String expression) {
DataDefinition dataSpec = new DataDefinition(UUID.randomUUID().toString(), "EXPRESSION (" + expression + ")", null);
DataDefinition dataSpec = new DataDefinition(UUID.randomUUID().toString(), "EXPRESSION (" + expression + ")", (String) null);
dataSpec.setExpression(expression);
return dataSpec;

}

private boolean isExpr(String mvelExpression) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.stream.Collectors;

import org.jbpm.process.builder.action.ActionCompilerRegistry;
import org.jbpm.process.builder.transformation.DataTransformerCompilerRegistry;
import org.jbpm.process.core.ContextContainer;
import org.jbpm.process.core.context.variable.Mappable;
import org.jbpm.process.core.context.variable.Variable;
Expand Down Expand Up @@ -69,6 +70,7 @@
import com.github.javaparser.ast.type.WildcardType;

import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
import static java.util.Collections.singletonList;
import static org.drools.util.StringUtils.ucFirst;
import static org.jbpm.ruleflow.core.Metadata.CUSTOM_AUTO_START;
import static org.jbpm.ruleflow.core.Metadata.HIDDEN;
Expand Down Expand Up @@ -230,7 +232,7 @@ protected Expression buildDataAssociationExpression(DataAssociation dataAssociat
DataDefinition targetExpr = dataAssociation.getTarget();
Transformation transformation = dataAssociation.getTransformation();
List<Assignment> assignments = dataAssociation.getAssignments();
return toDataAssociation(toDataDef(sourceExpr), toDataDef(targetExpr), toAssignmentExpr(assignments), toTransformation(transformation));
return toDataAssociation(toDataDef(sourceExpr), toDataDef(targetExpr), toAssignmentExpr(assignments), toTransformation(sourceExpr, singletonList(targetExpr), transformation));
}

private Expression toAssignmentExpr(List<Assignment> assignments) {
Expand All @@ -250,15 +252,15 @@ private Expression toAssignmentExpr(List<Assignment> assignments) {
return new MethodCallExpr(null, "java.util.Arrays.asList", NodeList.nodeList(expressions));
}

protected Expression toTransformation(Transformation transformation) {
protected Expression toTransformation(List<DataDefinition> inputs, List<DataDefinition> outputs, Transformation transformation) {
if (transformation == null) {
return new NullLiteralExpr();
}
Expression lang = new StringLiteralExpr(transformation.getLanguage());
Expression expression = new StringLiteralExpr(transformation.getExpression());
Expression source = new StringLiteralExpr(transformation.getSource());
Expression compiledExpression = DataTransformerCompilerRegistry.instance().find(transformation.getLanguage()).compile(inputs, outputs, transformation);
ClassOrInterfaceType clazz = new ClassOrInterfaceType(null, "org.jbpm.workflow.core.node.Transformation");
return new ObjectCreationExpr(null, clazz, NodeList.nodeList(lang, expression, source));
return new ObjectCreationExpr(null, clazz, NodeList.nodeList(lang, expression, compiledExpression));

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.jbpm.process.builder.transformation;

import java.util.List;

import org.jbpm.workflow.core.impl.DataDefinition;
import org.jbpm.workflow.core.node.Transformation;

import com.github.javaparser.ast.expr.Expression;

public interface DataTransformerCompiler {

default String[] dialects() {
return new String[0];
}

default boolean accept(String dialect) {
return List.of(dialects()).contains(dialect);
}

Expression compile(List<DataDefinition> inputs, List<DataDefinition> outputs, Transformation source);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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.jbpm.process.builder.transformation;

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

import org.jbpm.util.JbpmClassLoaderUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Registry for all available on runtime <code>DataTransformer</code>s for performing
* data input and output transformation.
* There is MVEL based transformer available out of the box that is registered under
* <code>http://www.mvel.org/2.0</code> key.
* <br/>
* Custom implementations can be provided and if they are compliant with JSR 223 then follows above registration approach
* otherwise they need to be registered manually with <code>register</code> method.
*
*/
public class DataTransformerCompilerRegistry {

private static final Logger logger = LoggerFactory.getLogger(DataTransformerCompilerRegistry.class);

private static DataTransformerCompilerRegistry INSTANCE;

private List<DataTransformerCompiler> registry;

public static DataTransformerCompilerRegistry instance() {
if (INSTANCE == null) {
INSTANCE = new DataTransformerCompilerRegistry();
}
return INSTANCE;
}

protected DataTransformerCompilerRegistry() {
this.registry = new ArrayList<>();
ServiceLoader.load(DataTransformerCompiler.class, JbpmClassLoaderUtil.findClassLoader()).forEach(registry::add);
}

public void register(DataTransformerCompiler transformer) {
this.registry.add(transformer);
logger.debug("Manual registration of scripting language {} with instance {}", transformer.dialects(), transformer);
}

public DataTransformerCompiler find(String language) {
for (DataTransformerCompiler transformer : registry) {
if (transformer.accept(language)) {
return transformer;
}
}
throw new IllegalArgumentException("transformer not support for dialect " + language);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.jbpm.process.builder.transformation;

import java.util.Collections;
import java.util.List;

import org.jbpm.process.core.impl.DataTransformerRegistry;
import org.jbpm.workflow.core.impl.DataDefinition;
import org.jbpm.workflow.core.node.Transformation;
import org.kie.kogito.internal.utils.ConversionUtils;

import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.FieldAccessExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;

public class DefaultDataTransformerCompiler implements DataTransformerCompiler {

@Override
public String[] dialects() {
return new String[] { "http://www.mvel.org/2.0" };
}

@Override
public Expression compile(List<DataDefinition> inputs, List<DataDefinition> outputs, Transformation transformation) {
Expression expr = null;
expr = new FieldAccessExpr(new NameExpr(DataTransformerRegistry.class.getPackageName()), DataTransformerRegistry.class.getSimpleName());
expr = new MethodCallExpr(expr, "get");
expr = new MethodCallExpr(expr, "find", NodeList.nodeList(new StringLiteralExpr(transformation.getLanguage())));

Expression emptyCollection = new MethodCallExpr(new FieldAccessExpr(new NameExpr(Collections.class.getPackageName()), Collections.class.getSimpleName()), "emptyMap");

expr = new MethodCallExpr(expr, "compile", NodeList.<Expression> nodeList(
new StringLiteralExpr(ConversionUtils.sanitizeString(transformation.getExpression())), emptyCollection));
return expr;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.jbpm.process.builder.transformation;

import java.util.List;
import java.util.Map;

import org.jbpm.workflow.core.impl.DataDefinition;
import org.jbpm.workflow.core.node.Transformation;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.AssignExpr;
import com.github.javaparser.ast.expr.CastExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.LambdaExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.expr.VariableDeclarationExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.type.ClassOrInterfaceType;

public class JavaDataTransformerCompiler implements DataTransformerCompiler {

@Override
public String[] dialects() {
return new String[] { "http://www.java.com/java" };
}

@Override
public Expression compile(List<DataDefinition> inputs, List<DataDefinition> outputs, Transformation transformation) {
// build lambda function
BlockStmt body = StaticJavaParser.parseBlock("{" + transformation.getExpression() + "}");
for (DataDefinition input : inputs) {
ClassOrInterfaceType type = StaticJavaParser.parseClassOrInterfaceType(input.getType());
VariableDeclarationExpr target = new VariableDeclarationExpr(type, input.getLabel());
Expression source = new CastExpr(type, new MethodCallExpr(new NameExpr("parameters"), "get", NodeList.nodeList(new StringLiteralExpr(input.getLabel()))));
AssignExpr assignment = new AssignExpr(target, source, AssignExpr.Operator.ASSIGN);
body.addStatement(0, assignment);
}

Expression lambda = new LambdaExpr(NodeList.nodeList(new Parameter(StaticJavaParser.parseClassOrInterfaceType(Map.class.getName()), "parameters")), body, true);
ClassOrInterfaceType type = StaticJavaParser.parseClassOrInterfaceType("java.util.function.Function<java.util.Map, Object>");
return new CastExpr(type, lambda);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.jbpm.process.builder.transformation.DefaultDataTransformerCompiler
org.jbpm.process.builder.transformation.JavaDataTransformerCompiler
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.jbpm.process.core.transformation.JavaDataTransformer;
import org.jbpm.process.core.transformation.MVELDataTransformer;
import org.kie.api.runtime.process.DataTransformer;
import org.slf4j.Logger;
Expand All @@ -46,6 +47,7 @@ public class DataTransformerRegistry {
protected DataTransformerRegistry() {
this.registry = new ConcurrentHashMap<>();
this.registry.put("http://www.mvel.org/2.0", new MVELDataTransformer());
this.registry.put("http://www.java.com/java", new JavaDataTransformer());
}

public static DataTransformerRegistry get() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.jbpm.process.core.transformation;

import java.util.Map;
import java.util.function.Function;

import org.kie.api.runtime.process.DataTransformer;

public class JavaDataTransformer implements DataTransformer {

@Override
public Object compile(String expression, Map<String, Object> parameters) {
return null;
}

@SuppressWarnings("unchecked")
@Override
public Object transform(Object expression, Map<String, Object> parameters) {
return ((Function<Map<String, Object>, Object>) expression).apply(parameters);
}

}
Loading

0 comments on commit 534f7dc

Please sign in to comment.