/* 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.activiti.workflow.simple.alfresco.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.ServiceTask;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.workflow.simple.alfresco.conversion.AlfrescoConversionConstants;
import org.activiti.workflow.simple.alfresco.conversion.AlfrescoConversionUtil;
import org.activiti.workflow.simple.alfresco.conversion.AlfrescoWorkflowDefinitionConversionFactory;
import org.activiti.workflow.simple.alfresco.conversion.script.PropertyReference;
import org.activiti.workflow.simple.alfresco.form.AlfrescoTransitionsPropertyDefinition;
import org.activiti.workflow.simple.alfresco.model.M2ClassAssociation;
import org.activiti.workflow.simple.alfresco.model.M2Model;
import org.activiti.workflow.simple.alfresco.model.M2Property;
import org.activiti.workflow.simple.alfresco.model.M2Type;
import org.activiti.workflow.simple.alfresco.model.config.Configuration;
import org.activiti.workflow.simple.alfresco.model.config.Module;
import org.activiti.workflow.simple.alfresco.step.AlfrescoEmailStepDefinition;
import org.activiti.workflow.simple.alfresco.step.AlfrescoReviewStepDefinition;
import org.activiti.workflow.simple.converter.WorkflowDefinitionConversion;
import org.activiti.workflow.simple.definition.HumanStepAssignment.HumanStepAssignmentType;
import org.activiti.workflow.simple.definition.HumanStepDefinition;
import org.activiti.workflow.simple.definition.WorkflowDefinition;
import org.activiti.workflow.simple.definition.form.FormDefinition;
import org.activiti.workflow.simple.definition.form.FormPropertyGroup;
import org.activiti.workflow.simple.definition.form.ListPropertyEntry;
import org.activiti.workflow.simple.definition.form.ReferencePropertyDefinition;
import org.activiti.workflow.simple.definition.form.TextPropertyDefinition;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class WorkflowDefinitionConversionTest {
protected AlfrescoWorkflowDefinitionConversionFactory conversionFactory;
@Before
public void init() {
conversionFactory = new AlfrescoWorkflowDefinitionConversionFactory();
}
/**
* Check if all required artifacts are created when converting an empty workflow-definition.
*/
@Test
public void testEmptyWorkflowDefinitionConversion() {
WorkflowDefinition definition = new WorkflowDefinition();
definition.setDescription("This is the description");
definition.setId("workflowdefinition");
definition.setName("My workflow definition");
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
BpmnModel bpmnModel = conversion.getBpmnModel();
assertNotNull(bpmnModel);
Process process = bpmnModel.getMainProcess();
assertNotNull(process);
assertEquals("This is the description", process.getDocumentation());
assertEquals("My workflow definition", process.getName());
assertEquals("workflowdefinition", process.getId());
// Default start-task key should be used, as no custom startform-config is present
boolean startTaskFound = false;
for(FlowElement element : process.getFlowElements()) {
if(element instanceof StartEvent) {
assertEquals("bpm:startTask", ((StartEvent) element).getFormKey());
startTaskFound = true;
}
}
assertTrue(startTaskFound);
// Check presence of content-model
M2Model contentModel = AlfrescoConversionUtil.getContentModel(conversion);
assertNotNull(contentModel);
// Check presence of form-config and default workflow-details
Module module = AlfrescoConversionUtil.getExtension(conversion).getModules().get(0);
assertNotNull(module);
assertEquals(1L, module.getConfigurations().size());
Configuration config = module.getConfigurations().get(0);
assertEquals(1L, config.getForms().size());
assertEquals("activiti$workflowdefinition", config.getCondition());
assertEquals(AlfrescoConversionConstants.EVALUATOR_STRING_COMPARE, config.getEvaluator());
}
/**
* Check if all required artifacts are created when converting an empty workflow-definition.
*/
@Test
public void testGeneratedWorkflowDefinitionId() {
WorkflowDefinition definition = new WorkflowDefinition();
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
BpmnModel bpmnModel = conversion.getBpmnModel();
assertNotNull(bpmnModel);
Process process = bpmnModel.getMainProcess();
assertNotNull(process);
String generatedProcessId = process.getId();
assertNotNull(generatedProcessId);
}
@Test
public void testTaskListenerForIncomingProperties() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setId("step1");
FormDefinition form = new FormDefinition();
form.setFormKey("myform");
humanStep.setForm(form);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
Process process = conversion.getProcess();
assertNotNull(process);
boolean listenerFound = false;
for(FlowElement flowElement : process.getFlowElements()) {
if(flowElement instanceof UserTask) {
UserTask task = (UserTask) flowElement;
assertNotNull(task.getTaskListeners());
assertEquals(1L, task.getTaskListeners().size());
assertEquals("create", task.getTaskListeners().get(0).getEvent());
listenerFound = true;
}
}
assertTrue(listenerFound);
}
@Test
public void testTaskListenerForOutgoingProperties() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setId("step1");
FormDefinition form = new FormDefinition();
humanStep.setForm(form);
TextPropertyDefinition text = new TextPropertyDefinition();
text.setName("my text");
text.getParameters().put(AlfrescoConversionConstants.PARAMETER_ADD_PROPERTY_TO_OUTPUT, true);
FormPropertyGroup group = new FormPropertyGroup();
group.setId("group");
form.getFormGroups().add(group);
group.getFormPropertyDefinitions().add(text);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
Process process = conversion.getProcess();
assertNotNull(process);
boolean listenerFound = false;
for(FlowElement flowElement : process.getFlowElements()) {
if(flowElement instanceof UserTask) {
UserTask task = (UserTask) flowElement;
assertNotNull(task.getTaskListeners());
assertEquals(2L, task.getTaskListeners().size());
assertEquals("create", task.getTaskListeners().get(0).getEvent());
assertEquals("complete", task.getTaskListeners().get(1).getEvent());
listenerFound = true;
}
}
assertTrue(listenerFound);
}
/**
* Check artifact export.
*/
@Test
public void testExportArtifacts() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setAssignee("fred");
humanStep.setId("step 1");
FormDefinition form = new FormDefinition();
form.setFormKey("wf:activitiAdhoc");
humanStep.setForm(form);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
conversionFactory.getArtifactExporter().writeBpmnModel(stream, conversion);
byte[] byteArray = stream.toByteArray();
assertTrue(byteArray.length > 0);
stream = new ByteArrayOutputStream();
conversionFactory.getArtifactExporter().writeContentModel(stream, conversion);
byteArray = stream.toByteArray();
assertTrue(byteArray.length > 0);
stream = new ByteArrayOutputStream();
conversionFactory.getArtifactExporter().writeShareConfig(stream, conversion, true);
byteArray = stream.toByteArray();
assertTrue(byteArray.length > 0);
stream = new ByteArrayOutputStream();
conversionFactory.getArtifactExporter().writeShareConfig(stream, conversion, false);
byteArray = stream.toByteArray();
assertTrue(byteArray.length > 0);
}
/**
* Test basic form-fields (text, number, date, list, ...)
*/
@Test
public void testHumanStepBasicFormField() throws Exception {
// TODO: finish test once all types are present
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setId("step1");
FormDefinition form = new FormDefinition();
humanStep.setForm(form);
FormPropertyGroup group = new FormPropertyGroup();
group.setId("group");
group.setTitle("My group");
humanStep.getForm().addFormPropertyGroup(group);
// Add simple text
TextPropertyDefinition textProperty = new TextPropertyDefinition();
textProperty.setName("text");
textProperty.setMandatory(true);
group.addFormProperty(textProperty);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
// Check content-model
M2Model model = AlfrescoConversionUtil.getContentModel(conversion);
assertNotNull(model);
M2Type type = model.getTypes().get(0);
assertNotNull(type);
// Simple text
M2Property property = getPropertyFromType("text", type);
assertEquals("d:text", property.getPropertyType());
assertEquals(Boolean.TRUE, property.getMandatory().isMandatory());
}
/**
* Test if a custom reference (eg. type=cm:person) is turned into an association on the
* model.
*/
@Test
public void testCustomReference() throws Exception {
// TODO: finish test once all types are present
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setId("step1");
FormDefinition form = new FormDefinition();
humanStep.setForm(form);
FormPropertyGroup group = new FormPropertyGroup();
group.setId("group");
group.setTitle("My group");
humanStep.getForm().addFormPropertyGroup(group);
// Add simple text
ReferencePropertyDefinition textProperty = new ReferencePropertyDefinition();
textProperty.setName("person");
textProperty.setMandatory(true);
textProperty.setType("cm:person");
group.addFormProperty(textProperty);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
// Check content-model
M2Model model = AlfrescoConversionUtil.getContentModel(conversion);
assertNotNull(model);
M2Type type = model.getTypes().get(0);
assertNotNull(type);
// Simple text
M2ClassAssociation association = getAssociationFromType("person", type);
assertEquals("cm:person", association.getTarget().getClassName());
assertTrue(association.getTarget().isMandatory());
}
@Test
public void testConvertEmailStep() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
AlfrescoEmailStepDefinition emailStep = new AlfrescoEmailStepDefinition();
emailStep.setTo("fred");
emailStep.setSubject("jos");
definition.addStep(emailStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
// Process should contain a single service-task
ServiceTask task = null;
for(FlowElement element : conversion.getProcess().getFlowElements()) {
if(element instanceof ServiceTask) {
if(task != null) {
Assert.fail("More than one service-task found");
}
task = (ServiceTask) element;
}
}
assertNotNull(task);
assertEquals(AlfrescoConversionConstants.CLASSNAME_SCRIPT_DELEGATE, task.getImplementation());
}
@Test
public void testPropertyReferenceParsing() throws Exception {
String absoluteReference = "{{Property Name}}";
assertTrue(PropertyReference.isPropertyReference(absoluteReference));
assertFalse(PropertyReference.isPropertyReference("{{incomplete}"));
assertTrue(PropertyReference.containsPropertyReference(absoluteReference));
assertEquals("test_propertyname", PropertyReference.createReference(absoluteReference).getVariableReference("test"));
String referenceWithProperties = "{{Property Name.test}}";
assertTrue(PropertyReference.isPropertyReference(referenceWithProperties));
assertTrue(PropertyReference.containsPropertyReference(referenceWithProperties));
assertEquals("test_propertyname.test", PropertyReference.createReference(referenceWithProperties).getVariableReference("test"));
absoluteReference = "{{Property Name.}}";
assertTrue(PropertyReference.isPropertyReference(absoluteReference));
assertFalse(PropertyReference.isPropertyReference("{{incomplete}"));
assertTrue(PropertyReference.containsPropertyReference(absoluteReference));
assertEquals("test_propertyname", PropertyReference.createReference(absoluteReference).getVariableReference("test"));
String referenceInText = "This is a {{reference}}";
assertEquals("This is a ${test_reference}", PropertyReference.replaceAllPropertyReferencesInString(referenceInText, "test", new ArrayList<PropertyReference>(), true));
assertEquals("This is a test_reference", PropertyReference.replaceAllPropertyReferencesInString(referenceInText, "test", new ArrayList<PropertyReference>(), false));
}
@Test
public void testTransitionProperty() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
HumanStepDefinition humanStep = new HumanStepDefinition();
humanStep.setId("step1");
FormDefinition form = new FormDefinition();
humanStep.setForm(form);
AlfrescoTransitionsPropertyDefinition transition = new AlfrescoTransitionsPropertyDefinition();
transition.addEntry(new ListPropertyEntry("One", "One"));
transition.addEntry(new ListPropertyEntry("Two", "Two"));
humanStep.getForm().addFormProperty(transition);
definition.addStep(humanStep);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
M2Model model = AlfrescoConversionUtil.getContentModel(conversion);
assertEquals(1L, model.getTypes().size());
M2Type taskType = model.getTypes().get(0);
assertEquals(1L, taskType.getPropertyOverrides().size());
assertEquals("bpm:outcomePropertyName", taskType.getPropertyOverrides().get(0).getName());
assertTrue(taskType.getPropertyOverrides().get(0).getDefaultValue().contains("step1transitions"));
assertEquals(1L, taskType.getProperties().size());
assertEquals(1L, model.getConstraints().size());
}
@Test
public void testReviewStep() throws Exception {
WorkflowDefinition definition = new WorkflowDefinition();
definition.setId("process");
AlfrescoReviewStepDefinition review = new AlfrescoReviewStepDefinition();
review.setName("Review");
review.setAssignmentPropertyName("bpm:people");
review.setAssignmentType(HumanStepAssignmentType.USERS);
review.setRequiredApprovalCount("1");
AlfrescoEmailStepDefinition emailStepDefinition = new AlfrescoEmailStepDefinition();
emailStepDefinition.setName("Send rejection email");
review.getRejectionSteps().add(emailStepDefinition);
definition.addStep(review);
WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(definition);
conversion.convert();
new File("target/repo").mkdir();
new File("target/share").mkdir();
conversionFactory.getArtifactExporter().exportArtifacts(conversion, new File("target/repo"), new File("target/share"), false);
}
protected M2Property getPropertyFromType(String shortName, M2Type type) {
for(M2Property prop : type.getProperties()) {
if(prop.getName().endsWith(shortName)) {
return prop;
}
}
Assert.fail("No property found for the given name: " + shortName);
return null;
}
protected M2ClassAssociation getAssociationFromType(String shortName, M2Type type) {
for(M2ClassAssociation assoc : type.getAssociations()) {
if(assoc.getName().endsWith(shortName)) {
return assoc;
}
}
Assert.fail("No association found for the given name: " + shortName);
return null;
}
}