/*
* 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.workbench.common.forms.jbpm.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.Dependent;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.bpmn2.Assignment;
import org.eclipse.bpmn2.DataInput;
import org.eclipse.bpmn2.DataInputAssociation;
import org.eclipse.bpmn2.DataOutput;
import org.eclipse.bpmn2.DataOutputAssociation;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.FormalExpression;
import org.eclipse.bpmn2.ItemDefinition;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.RootElement;
import org.eclipse.bpmn2.UserTask;
import org.kie.workbench.common.forms.jbpm.model.authoring.JBPMVariable;
import org.kie.workbench.common.forms.jbpm.model.authoring.process.BusinessProcessFormModel;
import org.kie.workbench.common.forms.jbpm.model.authoring.task.TaskFormModel;
import org.kie.workbench.common.forms.jbpm.server.service.BPMNFormModelGenerator;
import org.kie.workbench.common.forms.jbpm.service.bpmn.util.BPMNVariableUtils;
@Dependent
public class BPMNFormModelGeneratorImpl implements BPMNFormModelGenerator {
@Override
public BusinessProcessFormModel generateProcessFormModel(Definitions source) {
Process process = getProcess(source);
if (process != null) {
List<JBPMVariable> variables = new ArrayList<>();
process.getProperties().forEach(prop -> {
String varName = prop.getId();
String varType = getDefinitionType(prop.getItemSubjectRef());
variables.add(new JBPMVariable(varName,
varType));
});
return new BusinessProcessFormModel(process.getId(),
process.getName(),
variables);
}
return null;
}
@Override
public List<TaskFormModel> generateTaskFormModels(Definitions source) {
Process process = getProcess(source);
List<TaskFormModel> models = new ArrayList<>();
if (process != null) {
generateTaskFormModels(process,
models);
}
return models;
}
public void generateTaskFormModels(FlowElementsContainer container,
List<TaskFormModel> models) {
for (FlowElement fe : container.getFlowElements()) {
if (fe instanceof UserTask) {
models.add(getTaskFormModel((UserTask) fe,
container));
} else if (fe instanceof FlowElementsContainer) {
generateTaskFormModels((FlowElementsContainer) fe,
models);
}
}
}
@Override
public TaskFormModel generateTaskFormModel(Definitions source,
String taskId) {
Process process = getProcess(source);
if (process != null) {
return generateTaskFormModel(taskId,
process);
}
return null;
}
protected TaskFormModel generateTaskFormModel(String taskId,
FlowElementsContainer container) {
for (FlowElement fe : container.getFlowElements()) {
if (fe instanceof UserTask && fe.getId().equals(taskId)) {
return getTaskFormModel((UserTask) fe,
container);
} else if (fe instanceof FlowElementsContainer) {
TaskFormModel model = generateTaskFormModel(taskId,
(FlowElementsContainer) fe);
if (model != null) {
return model;
}
}
}
return null;
}
protected TaskFormModel getTaskFormModel(UserTask userTask,
FlowElementsContainer container) {
Map<String, JBPMVariable> taskVariables = new HashMap<>();
List<DataInputAssociation> dataInputAssociations = userTask.getDataInputAssociations();
String taskFormName = "";
if (dataInputAssociations != null) {
for (DataInputAssociation inputAssociation : dataInputAssociations) {
if (inputAssociation.getTargetRef() != null) {
String name = ((DataInput) inputAssociation.getTargetRef()).getName();
if (!BPMNVariableUtils.isValidInputName(name)) {
if (BPMNVariableUtils.TASK_FORM_VARIABLE.equals(name)) {
List<Assignment> assignments = inputAssociation.getAssignment();
for (Iterator<Assignment> it = assignments.iterator(); it.hasNext() && StringUtils.isEmpty(
taskFormName); ) {
Assignment assignment = it.next();
if (assignment.getFrom() != null) {
String taskName = ((FormalExpression) assignment.getFrom()).getBody();
if (!StringUtils.isEmpty(taskName)) {
taskFormName = taskName + BPMNVariableUtils.TASK_FORM_SUFFIX;
}
}
}
}
} else {
String type = getDefinitionType(inputAssociation.getTargetRef().getItemSubjectRef());
taskVariables.put(name,
new JBPMVariable(name,
type));
}
}
}
}
List<DataOutputAssociation> dataOutputAssociations = userTask.getDataOutputAssociations();
if (dataOutputAssociations != null) {
dataOutputAssociations.forEach(outputAssociation -> {
if (outputAssociation.getSourceRef() != null && outputAssociation.getSourceRef().size() == 1) {
String name = ((DataOutput) outputAssociation.getSourceRef().get(0)).getName();
if (!taskVariables.containsKey(name)) {
String type = getDefinitionType(outputAssociation.getSourceRef().get(0).getItemSubjectRef());
taskVariables.put(name,
new JBPMVariable(name,
type));
}
}
});
}
return new TaskFormModel(container.getId(),
userTask.getId(),
userTask.getName(),
taskFormName,
new ArrayList(taskVariables.values()));
}
protected Process getProcess(Definitions source) {
for (RootElement re : source.getRootElements()) {
if (re instanceof Process) {
return (Process) re;
}
}
return null;
}
private String getDefinitionType(ItemDefinition definition) {
String type = null;
if (definition != null) {
type = definition.getStructureRef();
}
return BPMNVariableUtils.getRealTypeForInput(type);
}
private class TaskVariableSetting {
private String variable;
private String input;
private String output;
private String type;
public TaskVariableSetting(String variable,
String type) {
this.variable = variable;
this.type = type;
}
public String getVariable() {
return variable;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
public String getType() {
return type;
}
}
}