diff --git a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/constants/BpmnXMLConstants.java b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/constants/BpmnXMLConstants.java index 4a35e15b83f..65708686a6e 100644 --- a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/constants/BpmnXMLConstants.java +++ b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/constants/BpmnXMLConstants.java @@ -85,6 +85,8 @@ public interface BpmnXMLConstants { public static final String ELEMENT_EVENT_LISTENER = "eventListener"; public static final String ELEMENT_TASK_LISTENER = "taskListener"; public static final String ELEMENT_SCRIPT = "script"; + public static final String ELEMENT_FORM_REFERENCE = "formreference"; + public static final String ATTRIBUTE_LISTENER_EVENT = "event"; public static final String ATTRIBUTE_LISTENER_EVENTS = "events"; public static final String ATTRIBUTE_LISTENER_ENTITY_TYPE = "entityType"; diff --git a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BpmnXMLConverter.java b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BpmnXMLConverter.java index 387c5572b4e..3a757824964 100644 --- a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BpmnXMLConverter.java +++ b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BpmnXMLConverter.java @@ -152,6 +152,7 @@ public class BpmnXMLConverter implements BpmnXMLConstants { addConverter(new ServiceTaskXMLConverter()); addConverter(new HttpServiceTaskXMLConverter()); addConverter(new CaseServiceTaskXMLConverter()); + addConverter(new FormAwareServiceTaskXMLConverter()); addConverter(new SendEventServiceTaskXMLConverter()); addConverter(new ExternalWorkerServiceTaskXMLConverter()); addConverter(new SendTaskXMLConverter()); diff --git a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/FormAwareServiceTaskXMLConverter.java b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/FormAwareServiceTaskXMLConverter.java new file mode 100644 index 00000000000..3f20440a0de --- /dev/null +++ b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/FormAwareServiceTaskXMLConverter.java @@ -0,0 +1,27 @@ +/* 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.flowable.bpmn.converter; + +import org.flowable.bpmn.model.BaseElement; +import org.flowable.bpmn.model.FormAwareServiceTask; + +/** + * @author Christopher Welsch + */ +public class FormAwareServiceTaskXMLConverter extends ServiceTaskXMLConverter { + + @Override + public Class getBpmnElementType() { + return FormAwareServiceTask.class; + } +} diff --git a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/ServiceTaskXMLConverter.java b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/ServiceTaskXMLConverter.java index 29af4bfb608..9511b3c865b 100644 --- a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/ServiceTaskXMLConverter.java +++ b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/ServiceTaskXMLConverter.java @@ -41,6 +41,7 @@ import org.flowable.bpmn.model.ExtensionAttribute; import org.flowable.bpmn.model.ExtensionElement; import org.flowable.bpmn.model.ExternalWorkerServiceTask; +import org.flowable.bpmn.model.FormAwareServiceTask; import org.flowable.bpmn.model.HttpServiceTask; import org.flowable.bpmn.model.ImplementationType; import org.flowable.bpmn.model.SendEventServiceTask; @@ -130,7 +131,19 @@ protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) serviceTask = new ExternalWorkerServiceTask(); } else { - serviceTask = new ServiceTask(); + String formKey = BpmnXMLUtil.getAttributeValue(ATTRIBUTE_FORM_FORMKEY, xtr); + if (StringUtils.isNotEmpty(formKey)) { + FormAwareServiceTask formAwareServiceTask = new FormAwareServiceTask(); + formAwareServiceTask.setFormKey(formKey); + + String formFieldValidation = BpmnXMLUtil.getAttributeValue(ATTRIBUTE_FORM_FIELD_VALIDATION, xtr); + if (StringUtils.isNotEmpty(formKey)) { + formAwareServiceTask.setValidateFormFields(formFieldValidation); + } + serviceTask = formAwareServiceTask; + } else { + serviceTask = new ServiceTask(); + } } BpmnXMLUtil.addXMLLocation(serviceTask, xtr); @@ -179,7 +192,6 @@ protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) } else { parseChildElements(getXMLElementName(), serviceTask, model, xtr); } - return serviceTask; } @@ -198,6 +210,9 @@ protected void writeAdditionalAttributes(BaseElement element, BpmnModel model, X writeHttpServiceTaskAdditionalAttributes((HttpServiceTask) element, model, xtw); } else { + if (element instanceof FormAwareServiceTask formAwareServiceTask) { + writeFormAwareServiceTaskAdditionalAttributes(formAwareServiceTask, xtw); + } writeServiceTaskAdditionalAttributes((ServiceTask) element, xtw); } } @@ -273,6 +288,16 @@ protected void writeHttpServiceTaskAdditionalAttributes(HttpServiceTask httpServ writeServiceTaskAdditionalAttributes(httpServiceTask, xtw); } + protected void writeFormAwareServiceTaskAdditionalAttributes(FormAwareServiceTask formAwareServiceTask, XMLStreamWriter xtw) throws Exception { + if (StringUtils.isNotEmpty(formAwareServiceTask.getFormKey())) { + writeQualifiedAttribute(ATTRIBUTE_FORM_FORMKEY, formAwareServiceTask.getFormKey(), xtw); + } + + if (StringUtils.isNotEmpty(formAwareServiceTask.getValidateFormFields())) { + writeQualifiedAttribute(ATTRIBUTE_FORM_FIELD_VALIDATION, formAwareServiceTask.getValidateFormFields(), xtw); + } + } + protected void writeServiceTaskAdditionalAttributes(ServiceTask element, XMLStreamWriter xtw) throws Exception { ServiceTask serviceTask = element; diff --git a/modules/flowable-bpmn-converter/src/main/resources/org/flowable/impl/bpmn/parser/flowable-bpmn-extensions.xsd b/modules/flowable-bpmn-converter/src/main/resources/org/flowable/impl/bpmn/parser/flowable-bpmn-extensions.xsd index b3776855c63..46b445c4ff7 100644 --- a/modules/flowable-bpmn-converter/src/main/resources/org/flowable/impl/bpmn/parser/flowable-bpmn-extensions.xsd +++ b/modules/flowable-bpmn-converter/src/main/resources/org/flowable/impl/bpmn/parser/flowable-bpmn-extensions.xsd @@ -55,7 +55,7 @@ - Attribute used on a startEvent or a userTask. + Attribute used on a startEvent, userTask or serviceTask. The value can be anything. The default form support in Flowable assumes that this is a reference to a form html file used in the deployment of the process definition. But this key can also be something completely different, @@ -81,7 +81,7 @@ Allows to specify a custom class that will be called during the parsing of the form information. This way, it is possible to use custom forms and form handling. This class must implement the - org.activiti.engine.inpl.form.FormHamdler/StartFormHandler/taskFormHandler interface + org.activiti.engine.impl.form.FormHandler/StartFormHandler/taskFormHandler interface (specific interface depending on the activity). @@ -96,8 +96,8 @@ - Subelement of the extensionsElement of activities that support forms. - Allows to specifies properties (!= process variables) for a form. See documentation chapter on + Sub element of the extensionsElement of activities that support forms. + Allows to specify properties (!= process variables) for a form. See documentation chapter on form properties. diff --git a/modules/flowable-bpmn-converter/src/test/java/org/flowable/editor/language/xml/FormAwareServiceTaskConverterTest.java b/modules/flowable-bpmn-converter/src/test/java/org/flowable/editor/language/xml/FormAwareServiceTaskConverterTest.java new file mode 100644 index 00000000000..6d6d2c5cc0a --- /dev/null +++ b/modules/flowable-bpmn-converter/src/test/java/org/flowable/editor/language/xml/FormAwareServiceTaskConverterTest.java @@ -0,0 +1,43 @@ +/* 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.flowable.editor.language.xml; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.bpmn.model.FieldExtension; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.FormAwareServiceTask; +import org.flowable.editor.language.xml.util.BpmnXmlConverterTest; + +class FormAwareServiceTaskConverterTest { + + @BpmnXmlConverterTest("formAwareServiceTask.bpmn") + void validateModelWithFormReference(BpmnModel model) { + FlowElement flowElement = model.getMainProcess().getFlowElement("servicetask"); + assertThat(flowElement) + .isInstanceOfSatisfying(FormAwareServiceTask.class, formAwareServiceTask -> { + assertThat(formAwareServiceTask.getId()).isEqualTo("servicetask"); + assertThat(formAwareServiceTask.getName()).isEqualTo("FormAwareServiceTask"); + assertThat(formAwareServiceTask.getImplementation()) + .isEqualTo("${delegateExpression}"); + assertThat(formAwareServiceTask.getImplementationType()) + .isEqualTo("delegateExpression"); + assertThat(formAwareServiceTask.getValidateFormFields()) + .isEqualTo("true"); + assertThat(formAwareServiceTask.getFormKey()) + .isEqualTo("someFormKey"); + }); + } +} diff --git a/modules/flowable-bpmn-converter/src/test/resources/formAwareServiceTask.bpmn b/modules/flowable-bpmn-converter/src/test/resources/formAwareServiceTask.bpmn new file mode 100644 index 00000000000..35c49d8fb52 --- /dev/null +++ b/modules/flowable-bpmn-converter/src/test/resources/formAwareServiceTask.bpmn @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-bpmn-model/src/main/java/org/flowable/bpmn/model/FormAwareServiceTask.java b/modules/flowable-bpmn-model/src/main/java/org/flowable/bpmn/model/FormAwareServiceTask.java new file mode 100644 index 00000000000..1ce43f6b344 --- /dev/null +++ b/modules/flowable-bpmn-model/src/main/java/org/flowable/bpmn/model/FormAwareServiceTask.java @@ -0,0 +1,42 @@ +/* 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.flowable.bpmn.model; + +import java.util.List; + +/** + * @author Christopher Welsch + */ +public class FormAwareServiceTask extends ServiceTask implements HasValidateFormFields { + + protected String validateFormFields; + protected String formKey; + + @Override + public String getValidateFormFields() { + return validateFormFields; + } + + @Override + public void setValidateFormFields(String validateFormFields) { + this.validateFormFields = validateFormFields; + } + + public String getFormKey() { + return formKey; + } + + public void setFormKey(String formKey) { + this.formKey = formKey; + } +} diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/TaskXmlConverter.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/TaskXmlConverter.java index bc3f59eb85b..2a0aba5934f 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/TaskXmlConverter.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/TaskXmlConverter.java @@ -21,6 +21,7 @@ import org.flowable.cmmn.model.CasePageTask; import org.flowable.cmmn.model.CmmnElement; import org.flowable.cmmn.model.ExternalWorkerServiceTask; +import org.flowable.cmmn.model.FormAwareServiceTask; import org.flowable.cmmn.model.HttpServiceTask; import org.flowable.cmmn.model.ImplementationType; import org.flowable.cmmn.model.ScriptServiceTask; @@ -52,7 +53,21 @@ protected CmmnElement convert(XMLStreamReader xtr, ConversionHelper conversionHe if (type != null) { if (Objects.equals(type, ServiceTask.JAVA_TASK)) { - task = convertToJavaServiceTask(xtr, className); + String formKey = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_FORM_KEY); + ServiceTask serviceTask; + + if (StringUtils.isNotEmpty(formKey)) { + FormAwareServiceTask formAwareServiceTask = new FormAwareServiceTask(); + formAwareServiceTask.setFormKey(formKey); + formAwareServiceTask.setValidateFormFields( + xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_FORM_FIELD_VALIDATION)); + serviceTask = formAwareServiceTask; + } else { + serviceTask = new ServiceTask(); + } + + convertToJavaServiceTask(xtr, className, serviceTask); + task = serviceTask; } else if (Objects.equals(type, HttpServiceTask.HTTP_TASK)) { task = convertToHttpTask(xtr, className); @@ -83,8 +98,7 @@ protected CmmnElement convert(XMLStreamReader xtr, ConversionHelper conversionHe return task; } - protected Task convertToJavaServiceTask(XMLStreamReader xtr, String className) { - ServiceTask serviceTask = new ServiceTask(); + protected void convertToJavaServiceTask(XMLStreamReader xtr, String className, ServiceTask serviceTask) { serviceTask.setType(ServiceTask.JAVA_TASK); String expression = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_EXPRESSION); @@ -110,7 +124,6 @@ protected Task convertToJavaServiceTask(XMLStreamReader xtr, String className) { serviceTask.setStoreResultVariableAsTransient( Boolean.parseBoolean(xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_STORE_RESULT_AS_TRANSIENT))); - return serviceTask; } protected Task convertToHttpTask(XMLStreamReader xtr, String className) { diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractServiceTaskExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractServiceTaskExport.java index e7338b596fe..b8bb8166ffc 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractServiceTaskExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractServiceTaskExport.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils; import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; +import org.flowable.cmmn.model.FormAwareServiceTask; import org.flowable.cmmn.model.HttpServiceTask; import org.flowable.cmmn.model.ImplementationType; import org.flowable.cmmn.model.ScriptServiceTask; @@ -118,4 +119,26 @@ protected Class getExportablePlanItemDefinitionClass() { return ScriptServiceTask.class; } } + + public static class FormAwareServiceTaskExport extends AbstractServiceTaskExport { + + @Override + protected Class getExportablePlanItemDefinitionClass() { + return FormAwareServiceTask.class; + } + + @Override + public void writePlanItemDefinitionSpecificAttributes(ServiceTask serviceTask, XMLStreamWriter xtw) throws Exception { + super.writePlanItemDefinitionSpecificAttributes(serviceTask, xtw); + FormAwareServiceTask formAwareServiceTask = (FormAwareServiceTask) serviceTask; + if (StringUtils.isNotBlank(formAwareServiceTask.getFormKey())) { + xtw.writeAttribute(FLOWABLE_EXTENSIONS_PREFIX, FLOWABLE_EXTENSIONS_NAMESPACE, ATTRIBUTE_FORM_KEY, formAwareServiceTask.getFormKey()); + } + if (StringUtils.isNotBlank(formAwareServiceTask.getValidateFormFields())) { + xtw.writeAttribute(FLOWABLE_EXTENSIONS_PREFIX, FLOWABLE_EXTENSIONS_NAMESPACE, ATTRIBUTE_FORM_FIELD_VALIDATION, + formAwareServiceTask.getValidateFormFields()); + } + } + } + } diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanItemDefinitionExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanItemDefinitionExport.java index 7fffc3d24b0..1f840f98427 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanItemDefinitionExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanItemDefinitionExport.java @@ -37,6 +37,7 @@ public class PlanItemDefinitionExport implements CmmnXmlConstants { addPlanItemDefinitionExport(new AbstractServiceTaskExport.ServiceTaskExport()); addPlanItemDefinitionExport(new AbstractServiceTaskExport.HttpServiceTaskExport()); addPlanItemDefinitionExport(new AbstractServiceTaskExport.ScriptServiceTaskExport()); + addPlanItemDefinitionExport(new AbstractServiceTaskExport.FormAwareServiceTaskExport()); addPlanItemDefinitionExport(new CasePageTaskExport()); addPlanItemDefinitionExport(new ExternalWorkerServiceTaskExport()); addPlanItemDefinitionExport(new MilestoneExport()); diff --git a/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/FormAwareServiceTaskConverterTest.java b/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/FormAwareServiceTaskConverterTest.java new file mode 100644 index 00000000000..a61ac639d6a --- /dev/null +++ b/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/FormAwareServiceTaskConverterTest.java @@ -0,0 +1,46 @@ +/* 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.flowable.test.cmmn.converter; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.flowable.cmmn.model.CmmnModel; +import org.flowable.cmmn.model.FormAwareServiceTask; +import org.flowable.cmmn.model.PlanItemDefinition; +import org.flowable.test.cmmn.converter.util.CmmnXmlConverterTest; + +/** + * @author Christopher Welsch + */ +class FormAwareServiceTaskConverterTest { + + @CmmnXmlConverterTest("org/flowable/test/cmmn/converter/formAwareServiceTask.cmmn") + public void validateModelWithCommaSeparatedStringExpressionCandidates(CmmnModel cmmnModel) { + assertThat(cmmnModel).isNotNull(); + + PlanItemDefinition itemDefinition = cmmnModel.findPlanItemDefinition("task1"); + assertThat(itemDefinition) + .isInstanceOfSatisfying(FormAwareServiceTask.class, formAwareServiceTask -> { + assertThat(formAwareServiceTask.getId()).isEqualTo("task1"); + assertThat(formAwareServiceTask.getName()).isEqualTo("FormAwareServiceTask"); + assertThat(formAwareServiceTask.getImplementationType()) + .isEqualTo("delegateExpression"); + assertThat(formAwareServiceTask.getValidateFormFields()) + .isEqualTo("true"); + assertThat(formAwareServiceTask.getFormKey()) + .isEqualTo("someFormKey"); + }); + + } + +} diff --git a/modules/flowable-cmmn-converter/src/test/resources/org/flowable/test/cmmn/converter/formAwareServiceTask.cmmn b/modules/flowable-cmmn-converter/src/test/resources/org/flowable/test/cmmn/converter/formAwareServiceTask.cmmn new file mode 100644 index 00000000000..960fb685f25 --- /dev/null +++ b/modules/flowable-cmmn-converter/src/test/resources/org/flowable/test/cmmn/converter/formAwareServiceTask.cmmn @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-cmmn-model/src/main/java/org/flowable/cmmn/model/FormAwareServiceTask.java b/modules/flowable-cmmn-model/src/main/java/org/flowable/cmmn/model/FormAwareServiceTask.java new file mode 100644 index 00000000000..40fe32768fa --- /dev/null +++ b/modules/flowable-cmmn-model/src/main/java/org/flowable/cmmn/model/FormAwareServiceTask.java @@ -0,0 +1,41 @@ +/* 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.flowable.cmmn.model; + +/** + * @author Christopher Welsch + */ +public class FormAwareServiceTask extends ServiceTask implements HasValidateFormFields { + + protected String validateFormFields; + protected String formKey; + + @Override + public String getValidateFormFields() { + return validateFormFields; + } + + @Override + public void setValidateFormFields(String validateFormFields) { + this.validateFormFields = validateFormFields; + } + + public String getFormKey() { + return formKey; + } + + public void setFormKey(String formKey) { + this.formKey = formKey; + } +} +