diff --git a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BaseBpmnXMLConverter.java b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BaseBpmnXMLConverter.java index 673822dfff0..d5430076ab7 100644 --- a/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BaseBpmnXMLConverter.java +++ b/modules/flowable-bpmn-converter/src/main/java/org/flowable/bpmn/converter/BaseBpmnXMLConverter.java @@ -164,13 +164,13 @@ public void convertToBpmnModel(XMLStreamReader xtr, BpmnModel model, Process act } } - public void convertToXML(XMLStreamWriter xtw, BaseElement baseElement, BpmnModel model) throws Exception { + public void convertToXML(XMLStreamWriter xtw, BaseElement baseElement, BpmnModel model, BpmnXMLConverterOptions options) throws Exception { xtw.writeStartElement(getXMLElementName()); boolean didWriteExtensionStartElement = false; writeDefaultAttribute(ATTRIBUTE_ID, baseElement.getId(), xtw); if (baseElement instanceof FlowElement) { String name = ((FlowElement) baseElement).getName(); - if (!BpmnXMLUtil.containsNewLine(name)) { + if (!(options.isSaveElementNameWithNewLineInExtensionElement() && BpmnXMLUtil.containsNewLine(name))) { writeDefaultAttribute(ATTRIBUTE_NAME, name, xtw); } } @@ -226,7 +226,9 @@ public void convertToXML(XMLStreamWriter xtw, BaseElement baseElement, BpmnModel xtw.writeEndElement(); } - didWriteExtensionStartElement = BpmnXMLUtil.writeElementNameExtensionElement(flowElement, didWriteExtensionStartElement, xtw); + if (options.isSaveElementNameWithNewLineInExtensionElement()) { + didWriteExtensionStartElement = BpmnXMLUtil.writeElementNameExtensionElement(flowElement, didWriteExtensionStartElement, xtw); + } } didWriteExtensionStartElement = writeExtensionChildElements(baseElement, didWriteExtensionStartElement, xtw); 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 80d1c8ad8d8..387c5572b4e 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 @@ -116,6 +116,8 @@ public class BpmnXMLConverter implements BpmnXMLConstants { protected List userTaskFormTypes; protected List startEventFormTypes; + protected BpmnXMLConverterOptions options = new BpmnXMLConverterOptions(); + protected BpmnEdgeParser bpmnEdgeParser = new BpmnEdgeParser(); protected BpmnShapeParser bpmnShapeParser = new BpmnShapeParser(); protected DefinitionsParser definitionsParser = new DefinitionsParser(); @@ -204,6 +206,14 @@ public static void addConverter(BaseBpmnXMLConverter converter, Class elementConverters = new HashMap<>(); + protected CmmnXmlConverterOptions options = new CmmnXmlConverterOptions(); + protected ClassLoader classloader; static { @@ -295,7 +297,7 @@ public byte[] convertToXML(CmmnModel model, String encoding) { Stage planModel = caseModel.getPlanModel(); - PlanItemDefinitionExport.writePlanItemDefinition(model, planModel, xtw); + PlanItemDefinitionExport.writePlanItemDefinition(model, planModel, xtw, options); // end case element xtw.writeEndElement(); @@ -719,6 +721,14 @@ protected void processAssociations(CmmnModel cmmnModel) { } } + public CmmnXmlConverterOptions getCmmnXmlConverterOptions() { + return options; + } + + public void setCmmnXmlConverterOptions(CmmnXmlConverterOptions options) { + this.options = options; + } + public void setClassloader(ClassLoader classloader) { this.classloader = classloader; } diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverterOptions.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverterOptions.java new file mode 100644 index 00000000000..c202df55178 --- /dev/null +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/CmmnXmlConverterOptions.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.cmmn.converter; + +public class CmmnXmlConverterOptions { + + protected boolean saveElementNameWithNewLineInExtensionElement = false; + + public boolean isSaveElementNameWithNewLineInExtensionElement() { + return saveElementNameWithNewLineInExtensionElement; + } + + public void setSaveElementNameWithNewLineInExtensionElement(boolean saveElementNameWithNewLineInExtensionElement) { + this.saveElementNameWithNewLineInExtensionElement = saveElementNameWithNewLineInExtensionElement; + } + +} diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractPlanItemDefinitionExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractPlanItemDefinitionExport.java index 3752c48978b..8be0a37b7f2 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractPlanItemDefinitionExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/AbstractPlanItemDefinitionExport.java @@ -16,6 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.flowable.cmmn.converter.CmmnXmlConstants; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.converter.util.CmmnXmlUtil; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.PlanItemDefinition; @@ -35,20 +36,20 @@ public abstract class AbstractPlanItemDefinitionExport { diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/CaseTaskExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/CaseTaskExport.java index ec6d7778395..669a5284b1d 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/CaseTaskExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/CaseTaskExport.java @@ -15,6 +15,7 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.commons.lang3.StringUtils; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CaseTask; import org.flowable.cmmn.model.CmmnModel; @@ -46,8 +47,8 @@ protected void writePlanItemDefinitionSpecificAttributes(CaseTask caseTask, XMLS } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, CaseTask caseTask, XMLStreamWriter xtw) throws Exception { - super.writePlanItemDefinitionBody(model, caseTask, xtw); + protected void writePlanItemDefinitionBody(CmmnModel model, CaseTask caseTask, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { + super.writePlanItemDefinitionBody(model, caseTask, xtw, options); // Always export the case reference as an expression, even if the caseRef is set if (StringUtils.isNotEmpty(caseTask.getCaseRef()) || StringUtils.isNotEmpty(caseTask.getCaseRefExpression())) { diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/DecisionTaskExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/DecisionTaskExport.java index dcb8d418d0e..7fbf28951e1 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/DecisionTaskExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/DecisionTaskExport.java @@ -15,6 +15,7 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.commons.lang3.StringUtils; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.DecisionTask; @@ -43,8 +44,8 @@ protected boolean writePlanItemDefinitionExtensionElements(CmmnModel model, Deci } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, DecisionTask decisionTask, XMLStreamWriter xtw) throws Exception { - super.writePlanItemDefinitionBody(model, decisionTask, xtw); + protected void writePlanItemDefinitionBody(CmmnModel model, DecisionTask decisionTask, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { + super.writePlanItemDefinitionBody(model, decisionTask, xtw, options); if (StringUtils.isNotEmpty(decisionTask.getDecisionRef()) || StringUtils.isNotEmpty(decisionTask.getDecisionRefExpression())) { xtw.writeStartElement(ELEMENT_DECISION_REF_EXPRESSION); xtw.writeCData( diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanFragmentExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanFragmentExport.java index 7540b18c480..7782026f22a 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanFragmentExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/PlanFragmentExport.java @@ -14,6 +14,7 @@ import javax.xml.stream.XMLStreamWriter; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.PlanFragment; import org.flowable.cmmn.model.PlanItem; @@ -49,8 +50,8 @@ protected void writePlanItemDefinitionSpecificAttributes(PlanFragment planFragme } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, PlanFragment planFragment, XMLStreamWriter xtw) throws Exception { - super.writePlanItemDefinitionBody(model, planFragment, xtw); + protected void writePlanItemDefinitionBody(CmmnModel model, PlanFragment planFragment, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { + super.writePlanItemDefinitionBody(model, planFragment, xtw, options); for (PlanItem planItem : planFragment.getPlanItems()) { PlanItemExport.writePlanItem(model, planItem, xtw); } 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 58b15008880..7fffc3d24b0 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 @@ -18,6 +18,7 @@ import javax.xml.stream.XMLStreamWriter; import org.flowable.cmmn.converter.CmmnXmlConstants; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.PlanItemDefinition; import org.flowable.common.engine.api.FlowableException; @@ -51,12 +52,12 @@ public static void addPlanItemDefinitionExport(AbstractPlanItemDefinitionExport planItemDefinitionExporters.put(exporter.getExportablePlanItemDefinitionClass().getCanonicalName(), exporter); } - public static void writePlanItemDefinition(CmmnModel model, PlanItemDefinition planItemDefinition, XMLStreamWriter xtw) throws Exception { + public static void writePlanItemDefinition(CmmnModel model, PlanItemDefinition planItemDefinition, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { AbstractPlanItemDefinitionExport exporter = determineExporter(planItemDefinition); if (exporter == null) { throw new FlowableException("Cannot find a PlanItemDefinitionExporter for '" + planItemDefinition.getClass().getCanonicalName() + "'"); } - exporter.writePlanItemDefinition(model, planItemDefinition, xtw); + exporter.writePlanItemDefinition(model, planItemDefinition, xtw, options); } protected static AbstractPlanItemDefinitionExport determineExporter(PlanItemDefinition planItemDefinition) { diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/ProcessTaskExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/ProcessTaskExport.java index b31727efe2e..0e5f4358f70 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/ProcessTaskExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/ProcessTaskExport.java @@ -15,6 +15,7 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.commons.lang3.StringUtils; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.ProcessTask; @@ -47,8 +48,8 @@ protected void writePlanItemDefinitionSpecificAttributes(ProcessTask processTask } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, ProcessTask processTask, XMLStreamWriter xtw) throws Exception { - super.writePlanItemDefinitionBody(model, processTask, xtw); + protected void writePlanItemDefinitionBody(CmmnModel model, ProcessTask processTask, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { + super.writePlanItemDefinitionBody(model, processTask, xtw, options); if (StringUtils.isNotEmpty(processTask.getProcessRef()) || StringUtils.isNotEmpty(processTask.getProcessRefExpression())) { xtw.writeStartElement(ELEMENT_PROCESS_REF_EXPRESSION); diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/StageExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/StageExport.java index 77cd30a4e78..0160a489d3b 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/StageExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/StageExport.java @@ -15,6 +15,7 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.commons.lang3.StringUtils; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.PlanItem; import org.flowable.cmmn.model.PlanItemDefinition; @@ -81,8 +82,8 @@ protected void writePlanItemDefinitionSpecificAttributes(Stage stage, XMLStreamW } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, Stage stage, XMLStreamWriter xtw) throws Exception { - super.writePlanItemDefinitionBody(model, stage, xtw); + protected void writePlanItemDefinitionBody(CmmnModel model, Stage stage, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { + super.writePlanItemDefinitionBody(model, stage, xtw, options); for (PlanItem planItem : stage.getPlanItems()) { PlanItemExport.writePlanItem(model, planItem, xtw); } @@ -92,7 +93,7 @@ protected void writePlanItemDefinitionBody(CmmnModel model, Stage stage, XMLStre } for (PlanItemDefinition planItemDefinition : stage.getPlanItemDefinitions()) { - PlanItemDefinitionExport.writePlanItemDefinition(model, planItemDefinition, xtw); + PlanItemDefinitionExport.writePlanItemDefinition(model, planItemDefinition, xtw, options); } if (stage.isPlanModel() && stage.getExitCriteria() != null && !stage.getExitCriteria().isEmpty()) { diff --git a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/TimerEventListenerExport.java b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/TimerEventListenerExport.java index f1cb051178a..39483c50fc3 100644 --- a/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/TimerEventListenerExport.java +++ b/modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/export/TimerEventListenerExport.java @@ -16,6 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.flowable.cmmn.converter.CmmnXmlConstants; +import org.flowable.cmmn.converter.CmmnXmlConverterOptions; import org.flowable.cmmn.model.CmmnModel; import org.flowable.cmmn.model.TimerEventListener; @@ -46,7 +47,7 @@ protected void writePlanItemDefinitionSpecificAttributes(TimerEventListener time } @Override - protected void writePlanItemDefinitionBody(CmmnModel model, TimerEventListener timerEventListener, XMLStreamWriter xtw) throws Exception { + protected void writePlanItemDefinitionBody(CmmnModel model, TimerEventListener timerEventListener, XMLStreamWriter xtw, CmmnXmlConverterOptions options) throws Exception { if (StringUtils.isNotEmpty(timerEventListener.getTimerExpression())) { xtw.writeStartElement(ELEMENT_TIMER_EXPRESSION); xtw.writeCData(timerEventListener.getTimerExpression()); diff --git a/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/util/XmlTestUtils.java b/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/util/XmlTestUtils.java index f174d25aa9a..7de1968e133 100644 --- a/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/util/XmlTestUtils.java +++ b/modules/flowable-cmmn-converter/src/test/java/org/flowable/test/cmmn/converter/util/XmlTestUtils.java @@ -31,12 +31,18 @@ public static CmmnModel readXmlExportAndReadAgain(String resource) { } public static CmmnModel exportAndReadXMLFile(CmmnModel model) { - byte[] xml = new CmmnXmlConverter().convertToXML(model); - return new CmmnXmlConverter().convertToCmmnModel(new InputStreamSource(new ByteArrayInputStream(xml)), true, false, "UTF-8"); + byte[] xml = getCmmnXmlConverter().convertToXML(model); + return getCmmnXmlConverter().convertToCmmnModel(new InputStreamSource(new ByteArrayInputStream(xml)), true, false, "UTF-8"); } public static CmmnModel readXMLFile(String resource) { - return new CmmnXmlConverter().convertToCmmnModel(new ClasspathStreamResource(resource), true, false); + return getCmmnXmlConverter().convertToCmmnModel(new ClasspathStreamResource(resource), true, false); + } + + private static CmmnXmlConverter getCmmnXmlConverter() { + CmmnXmlConverter converter = new CmmnXmlConverter(); + converter.getCmmnXmlConverterOptions().setSaveElementNameWithNewLineInExtensionElement(true); + return converter; } protected static class ClasspathStreamResource implements InputStreamProvider {