From 4190ad19f422bfd342a26ae07b675ce1e877a77c Mon Sep 17 00:00:00 2001 From: Ralph Soika <ralph.soika@imixs.com> Date: Sat, 18 Feb 2023 16:34:09 +0100 Subject: [PATCH] refactoring Issue #183 --- .../AbstractBPMNElementExtension.java | 50 ++- .../ConditionalEventDefinitionExtension.java | 179 ++++++++ .../DefaultBPMNDataObjectExtension.java | 41 +- .../DefaultBPMNDefinitionsExtension.java | 73 ++-- .../extension/DefaultBPMNEdgeExtension.java | 34 +- .../extension/DefaultBPMNEventExtension.java | 398 ++---------------- .../DefaultBPMNGatewayExtension.java | 51 +-- .../DefaultBPMNMessageExtension.java | 41 +- .../DefaultBPMNParticipantExtension.java | 104 ++--- .../DefaultBPMNSequenceFlowExtension.java | 5 +- .../extension/DefaultBPMNTaskExtension.java | 48 +-- .../DefaultBPMNTextAnnotationExtension.java | 49 +-- .../LinkEventDefinitionExtension.java | 143 +++++++ .../SignalEventDefinitionExtension.java | 187 ++++++++ .../TimerEventDefinitionExtension.java | 75 +--- .../org/openbpmn/glsp/BPMNDiagramModule.java | 6 + .../glsp/model/BPMNGModelFactory.java | 11 +- .../bpmn/elements/core/BPMNElement.java | 12 +- 18 files changed, 753 insertions(+), 754 deletions(-) create mode 100644 open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/ConditionalEventDefinitionExtension.java create mode 100644 open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/LinkEventDefinitionExtension.java create mode 100644 open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/SignalEventDefinitionExtension.java diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/AbstractBPMNElementExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/AbstractBPMNElementExtension.java index f5ce0d39..a456a911 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/AbstractBPMNElementExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/AbstractBPMNElementExtension.java @@ -15,8 +15,21 @@ ********************************************************************************/ package org.openbpmn.extension; +import java.util.Optional; + +import javax.json.JsonObject; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.glsp.graph.GModelElement; +import org.eclipse.glsp.graph.GNode; import org.openbpmn.bpmn.BPMNNS; import org.openbpmn.bpmn.elements.core.BPMNElement; +import org.openbpmn.glsp.bpmn.LabelGNode; +import org.openbpmn.glsp.model.BPMNGModelState; +import org.openbpmn.glsp.utils.BPMNGraphUtil; + +import com.google.inject.Inject; /** * This is Abstract implementation provides some core funtionallity like update @@ -28,6 +41,15 @@ */ abstract class AbstractBPMNElementExtension implements BPMNExtension { + private static Logger logger = LogManager.getLogger(AbstractBPMNElementExtension.class); + + @Inject + protected BPMNGModelState modelState; + + public BPMNGModelState getModelState() { + return modelState; + } + /** * Returns the Extension label to be used in the Tool Palette. The default name * is the namespace. Implementations should overwrite this method. @@ -61,7 +83,33 @@ public String getNamespaceURI() { @Override public int getPriority() { - return 999999; + return 1; + } + + /** + * This method updates the name attribute of a BPMNElement and also the + * corresponding GNode Element in the diagram plane. + * + * @param json + * @param bpmnElement + * @param gNodeElement + */ + public void updateNameProperty(final JsonObject json, BPMNElement bpmnElement, final GModelElement gNodeElement) { + // Update the name feature + String name = json.getString("name", ""); + if (!name.equals(bpmnElement.getName())) { + bpmnElement.setName(name); + // Update Label... + Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); + if (!label.isEmpty()) { + LabelGNode lgn = (LabelGNode) label.get(); + // update the bpmn-text-node of the GNodeElement + GNode gnode = BPMNGraphUtil.findMultiLineTextNode(lgn); + if (gnode != null) { + gnode.getArgs().put("text", name); + } + } + } } } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/ConditionalEventDefinitionExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/ConditionalEventDefinitionExtension.java new file mode 100644 index 00000000..a2562e73 --- /dev/null +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/ConditionalEventDefinitionExtension.java @@ -0,0 +1,179 @@ +/******************************************************************************** + * Copyright (c) 2022 Imixs Software Solutions GmbH and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.openbpmn.extension; + +import java.util.Iterator; +import java.util.Set; + +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.glsp.graph.GModelElement; +import org.openbpmn.bpmn.BPMNTypes; +import org.openbpmn.bpmn.elements.Event; +import org.openbpmn.bpmn.elements.core.BPMNElement; +import org.openbpmn.glsp.jsonforms.DataBuilder; +import org.openbpmn.glsp.jsonforms.SchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; +import org.w3c.dom.Element; + +/** + * The TimerEventDefinitionExtension is responsible to read and update optional + * TimerEventDefinitions from the BPMN model. The Extension builds a custom + * property section named 'Timers' shown a list of all TimerEventDefinitions + * define in a Event. + * + * @author rsoika + */ +public class ConditionalEventDefinitionExtension extends DefaultBPMNEventExtension { + + private static Logger logger = LogManager.getLogger(DefaultBPMNSequenceFlowExtension.class); + + @Override + public int getPriority() { + return 101; + } + + /** + * Returns if this Extension can be applied to the given elementTypeID + */ + @Override + public boolean handlesElementTypeId(final String elementTypeId) { + return BPMNTypes.BPMN_EVENTS.contains(elementTypeId); + } + + /** + * This Helper Method generates a JSON Object with the BPMNElement properties. + * <p> + * This json object is used on the GLSP Client to generate the EMF JsonForms + */ + @Override + public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder dataBuilder, + final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { + + Event event = (Event) bpmnElement; + + // Conditional + + Set<Element> conditionalEventDefinition = event.getEventDefinitionsByType("conditionalEventDefinition"); + + if (conditionalEventDefinition.size() > 0) { + + JsonObject multilineOption = Json.createObjectBuilder() // + .add("multi", true).build(); + + uiSchemaBuilder. // + addCategory("Conditions"). // + addLayout(Layout.VERTICAL); + + // create a detail control Layout.... + JsonArrayBuilder controlsArrayBuilder = Json.createArrayBuilder(); + controlsArrayBuilder // + .add(Json.createObjectBuilder() // + .add("type", "Control") // + .add("scope", "#/properties/language"))// + .add(Json.createObjectBuilder() // + .add("type", "Control") // + .add("scope", "#/properties/expression") // + .add("label", "Expression") // + .add("options", multilineOption) // + ); + + JsonObjectBuilder detailLayoutBuilder = Json.createObjectBuilder(). // + add("type", "VerticalLayout"). /// + add("elements", controlsArrayBuilder); + + JsonObjectBuilder detailBuilder = Json.createObjectBuilder(). // + add("detail", detailLayoutBuilder.build()); + uiSchemaBuilder.addDetailLayout("conditions", "Conditions", detailBuilder.build()); + + /* + * Add the Schema .... + */ + schemaBuilder.addArray("conditions"); + schemaBuilder.addProperty("language", "string", null, null); + schemaBuilder.addProperty("expression", "string", null, null); + + /* + * Now we can create the data structure - each conditionalEventDefinition is + * represented as a separate object + */ + dataBuilder.addArray("conditions"); + for (Element definition : conditionalEventDefinition) { + dataBuilder.addObject(); + dataBuilder.addData("language", definition.getAttribute("language")); + dataBuilder.addData("expression", definition.getAttribute("expression")); + } + + } + } + + /** + * Update the timers definitions + * + * This method updates all timerEventDefinitions. The method expects a + * dataList containing all timer definitions with its values. + * The method simply overwrites all timerEventDefinitions. + * <p> + * Example: + * + * <pre> + * {@code + * <bpmn2:startEvent id="event_n8bj0g" name="Event-1"> + * <bpmn2:documentation id="documentation_4XhEKA"/> + * <bpmn2:timerEventDefinition id="timerEventDefinition_hElKhw"> + * <bpmn2:timeDuration id="FormalExpression_0" xsi:type= + "bpmn2:tFormalExpression">3cc</bpmn2:timeDuration> + * </bpmn2:timerEventDefinition> + * </bpmn2:startEvent> + * } + * </pre> + */ + @Override + public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, + final GModelElement gNodeElement) { + Event bpmnEvent = (Event) bpmnElement; + JsonArray dataList = json.getJsonArray("conditions"); + + // synchronize the definition list of the event element + Set<Element> conditionalEventDefinitions = synchronizeEventDefinitions("conditionalEventDefinition", bpmnEvent, + dataList); + + // now we can update the values one by one + // NOTE: the id can change within the definitionList if an element was deleted + // or moved! + // but we do not care about this issue. + Iterator<Element> iter = conditionalEventDefinitions.iterator(); + int i = 0; + while (iter.hasNext()) { + Element eventDefinitionElement = iter.next(); + JsonObject jsonData = dataList.getJsonObject(i); // .get(i); + if (jsonData != null) { + eventDefinitionElement.setAttribute("language", jsonData.getString("language", "")); + eventDefinitionElement.setAttribute("expression", jsonData.getString("expression", "")); + } + i++; + // update completed + } + + } +} diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDataObjectExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDataObjectExtension.java index 7407ae1d..03d63707 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDataObjectExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDataObjectExtension.java @@ -17,24 +17,18 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.Set; import javax.json.JsonObject; import org.eclipse.glsp.graph.GModelElement; -import org.eclipse.glsp.graph.GNode; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.DataObject; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.bpmn.elements.core.BPMNElementNode; -import org.openbpmn.glsp.bpmn.LabelGNode; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; import org.openbpmn.glsp.model.BPMNGModelState; -import org.openbpmn.glsp.utils.BPMNGraphUtil; import com.google.inject.Inject; @@ -94,37 +88,14 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Update the DataObject properties + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - - // default update of name and documentation - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("name".equals(feature)) { - String text = json.getString(feature); - bpmnElement.setName(text); - // Update GModelElement Label... - Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); - if (!label.isEmpty()) { - LabelGNode lgn = (LabelGNode) label.get(); - // update the bpmn-text-node of the GNodeElement - GNode gnode = BPMNGraphUtil.findMultiLineTextNode(lgn); - if (gnode != null) { - gnode.getArgs().put("text", text); - } - continue; - } - continue; - } - if ("documentation".equals(feature)) { - ((BPMNElementNode) bpmnElement).setDocumentation(json.getString(feature)); - continue; - } - - } - + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); } - } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDefinitionsExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDefinitionsExtension.java index c177e837..38003b7e 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDefinitionsExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNDefinitionsExtension.java @@ -17,7 +17,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Set; import javax.json.Json; import javax.json.JsonArray; @@ -122,57 +121,37 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Updates the BPMN Diagram definition properties + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { Element definitions = modelState.getBpmnModel().getDefinitions(); - // check custom features - Set<String> features = json.keySet(); - for (String feature : features) { - if ("name".equals(feature)) { - bpmnElement.setName(json.getString(feature)); - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - if ("targetNamespace".equals(feature)) { - definitions.setAttribute(feature, json.getString(feature)); - continue; - } - if ("exporter".equals(feature)) { - definitions.setAttribute(feature, json.getString(feature)); - continue; - } - if ("exporterVersion".equals(feature)) { - definitions.setAttribute(feature, json.getString(feature)); - continue; - } - // Signals... - if ("signals".equals(feature)) { - logger.debug("...update feature = " + feature); - JsonArray signalSetValues = json.getJsonArray(feature); - for (JsonValue laneValue : signalSetValues) { - // update signal properties - JsonObject signalData = (JsonObject) laneValue; - - String id = signalData.getString("id", null); - Signal signal = (Signal) modelState.getBpmnModel().findElementById(id); - if (signal != null) { - signal.setName(signalData.getString("name")); - } else { - // signal did not yet exist in definition list - so we create a new one - int i = modelState.getBpmnModel().getSignals().size() + 1; - try { - modelState.getBpmnModel().addSignal("signal_" + i, "Signal " + i); - modelState.reset(); - } catch (BPMNModelException e) { - logger.warn("Unable to add new signal: " + e.getMessage()); - } - - } + bpmnElement.setName(json.getString("name")); + bpmnElement.setDocumentation(json.getString("documentation")); + definitions.setAttribute("targetNamespace", json.getString("targetNamespace")); + definitions.setAttribute("exporter", json.getString("exporter")); + definitions.setAttribute("exporterVersion", json.getString("exporterVersion")); + + // update signal properties... + logger.debug("...update signals.. "); + JsonArray signalSetValues = json.getJsonArray("signals"); + for (JsonValue laneValue : signalSetValues) { + JsonObject signalData = (JsonObject) laneValue; + String id = signalData.getString("id", null); + Signal signal = (Signal) modelState.getBpmnModel().findElementById(id); + if (signal != null) { + signal.setName(signalData.getString("name")); + } else { + // signal did not yet exist in definition list - so we create a new one + int i = modelState.getBpmnModel().getSignals().size() + 1; + try { + modelState.getBpmnModel().addSignal("signal_" + i, "Signal " + i); + modelState.reset(); + } catch (BPMNModelException e) { + logger.warn("Unable to add new signal: " + e.getMessage()); } } } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEdgeExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEdgeExtension.java index 89a4345f..deb6b81f 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEdgeExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEdgeExtension.java @@ -17,14 +17,11 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.Set; import javax.json.JsonObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.eclipse.glsp.graph.GLabel; import org.eclipse.glsp.graph.GModelElement; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.core.BPMNElement; @@ -101,35 +98,14 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } /** - * This Helper Method updates the BPMNElement data properties. - * <p> + * Update the default edge properties. + * */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("name".equals(feature)) { - bpmnElement.setName(json.getString(feature)); - // Update Label... - Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); - if (!label.isEmpty()) { - GLabel glabel = (GLabel) label.get(); - if (glabel != null) { - glabel.setText(json.getString(feature)); - } - } - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - - } - + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); } - } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEventExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEventExtension.java index 9600a8a3..6aff942a 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEventExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNEventExtension.java @@ -16,38 +16,24 @@ package org.openbpmn.extension; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; -import javax.json.Json; import javax.json.JsonArray; -import javax.json.JsonArrayBuilder; import javax.json.JsonObject; -import javax.json.JsonObjectBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.glsp.graph.GModelElement; -import org.eclipse.glsp.graph.GNode; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Event; -import org.openbpmn.bpmn.elements.Signal; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.bpmn.exceptions.BPMNInvalidReferenceException; -import org.openbpmn.bpmn.exceptions.BPMNInvalidTypeException; -import org.openbpmn.bpmn.exceptions.BPMNMissingElementException; import org.openbpmn.bpmn.exceptions.BPMNModelException; -import org.openbpmn.glsp.bpmn.LabelGNode; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; import org.openbpmn.glsp.model.BPMNGModelState; -import org.openbpmn.glsp.utils.BPMNGraphUtil; import org.w3c.dom.Element; import com.google.inject.Inject; @@ -59,8 +45,7 @@ * */ public class DefaultBPMNEventExtension extends AbstractBPMNElementExtension { - - private static Logger logger = LogManager.getLogger(DefaultBPMNEventExtension.class); + private static Logger logger = LogManager.getLogger(DefaultBPMNTaskExtension.class); @Inject protected BPMNGModelState modelState; @@ -107,8 +92,6 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder addProperty("name", "string", null). // addProperty("documentation", "string", null); - Event bpmnEvent = (Event) bpmnElement; - Map<String, String> multilineOption = new HashMap<>(); multilineOption.put("multi", "true"); Map<String, String> radioOption = new HashMap<>(); @@ -120,22 +103,6 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder addElements("name"). // addElement("documentation", "Documentation", multilineOption); - Set<Element> eventDefinitions = bpmnEvent.getEventDefinitions(); - // Conditional - List<Element> conditionalEventDefinitions = eventDefinitions.stream() - .filter(c -> "conditionalEventDefinition".equals(c.getLocalName())).collect(Collectors.toList()); - addConditionalEventDefinitions(conditionalEventDefinitions, dataBuilder, schemaBuilder, uiSchemaBuilder); - - // Signal - List<Element> signalEventDefinitions = eventDefinitions.stream() - .filter(c -> "signalEventDefinition".equals(c.getLocalName())).collect(Collectors.toList()); - addSignalEventDefinitions(signalEventDefinitions, dataBuilder, schemaBuilder, uiSchemaBuilder); - - // Link - List<Element> linkEventDefinitions = eventDefinitions.stream() - .filter(c -> "linkEventDefinition".equals(c.getLocalName())).collect(Collectors.toList()); - addLinkEventDefinitions(linkEventDefinitions, dataBuilder, schemaBuilder, uiSchemaBuilder); - } /** @@ -147,355 +114,56 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - Event bpmnEvent = (Event) bpmnElement; - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("name".equals(feature)) { - String text = json.getString(feature); - bpmnElement.setName(text); - // Update Label... - Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); - if (!label.isEmpty()) { - LabelGNode lgn = (LabelGNode) label.get(); - // update the bpmn-text-node of the GNodeElement - GNode gnode = BPMNGraphUtil.findMultiLineTextNode(lgn); - if (gnode != null) { - gnode.getArgs().put("text", text); - } - continue; - } - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - - // Update eventDefinitions for each definition type... - Set<Element> eventDefinitions = bpmnEvent.getEventDefinitions(); - if ("signals".equals(feature)) { - JsonArray signalDataList = json.getJsonArray("signals"); - updateSignalEventDefinitions(bpmnEvent, signalDataList); - } - if ("conditions".equals(feature)) { - JsonArray conditionsDataList = json.getJsonArray("conditions"); - updateConditionalEventDefinitions(bpmnEvent, conditionsDataList); - } - if ("links".equals(feature)) { - JsonArray signalDataList = json.getJsonArray("links"); - // find all Signal definitions of this event - List<Element> conditionalEventDefinitions = eventDefinitions.stream() - .filter(c -> "linkEventDefinition".equals(c.getLocalName())).collect(Collectors.toList()); - updateLinkEventDefinitions(conditionalEventDefinitions, signalDataList); - } - } - - } - - /* - * This method updates the signalEventDefinitions. The method expects a - * dataList containing all conditions with its values (including the id). - * The method simply overwrites all csignalEventDefinitions. - * - * @See addSignalEventDefinitions how we map between the signal name and its id. - */ - private void updateSignalEventDefinitions(final Event bpmnEvent, final JsonArray dataList) { - - // find all conditionalEventDefinitions for this event - Set<Element> signalEventDefinitions = bpmnEvent.getEventDefinitionsByType("signalEventDefinition"); - // If the size of the conditionalDataList is not equals the size of the - // DefinitionList we add or remove conditions... - while (signalEventDefinitions.size() != dataList.size()) { - try { - if (signalEventDefinitions.size() < dataList.size()) { - // add a new empty condition placeholder... - bpmnEvent.addEventDefinition("signalEventDefinition"); - } - if (signalEventDefinitions.size() > dataList.size()) { - // delete first condition from the list - Element definition = signalEventDefinitions.iterator().next(); - String id = definition.getAttribute("id"); - bpmnEvent.deleteEventDefinition(id); - } - } catch (BPMNModelException e) { - logger.error("Failed to update BPMN Event Definition list: " + e.getMessage()); - e.printStackTrace(); - } - // Update event definition list - signalEventDefinitions = bpmnEvent.getEventDefinitionsByType("signalEventDefinition"); - } - - // now we can update the values one by referring to the signalRef id by - // comparing the name - Iterator<Element> iter = signalEventDefinitions.iterator(); - int i = 0; - while (iter.hasNext()) { - Element eventDefinitionElement = iter.next(); - JsonObject jsonData = dataList.getJsonObject(i); // .get(i); - if (jsonData != null) { - - String signalName = ""; - - try { - signalName = jsonData.getString("signal"); - } catch (NullPointerException en) { - // no name defined! - } - logger.debug("signal=" + signalName); - try { - // fetch the signal from teh Model Signal list by name... - Signal signal = modelState.getBpmnModel().findSignalByName(signalName); - if (signal != null) { - eventDefinitionElement.setAttribute("signalRef", signal.getId()); - } else { - // no signal defintion found - delete signalRef... - eventDefinitionElement.setAttribute("signalRef", ""); - } - } catch (BPMNInvalidReferenceException | BPMNMissingElementException | BPMNInvalidTypeException e) { - e.printStackTrace(); - } - } - i++; - // update completed - } + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); } /** - * This method updates the conditionalEventDefinitions. The method expects a - * dataList containing all conditions with its values (including the id). - * The method simpl overwrites all conditionalEventDefinitions. + * This helper method verifies if the count of definitions matches the given + * size of a dataList containing definition data and updates the elements + * definition list. + * The method returns an updated list of definition elements * + * @param definitionName * @param bpmnEvent * @param dataList + * @return - updated list of definition elements */ - private void updateConditionalEventDefinitions(final Event bpmnEvent, final JsonArray dataList) { - // find all conditionalEventDefinitions for this event - Set<Element> conditionalEventDefinitions = bpmnEvent.getEventDefinitionsByType("conditionalEventDefinition"); - // If the size of the conditionalDataList is not equals the size of the - // DefinitionList we add or remove conditions... - while (conditionalEventDefinitions.size() != dataList.size()) { + Set<Element> synchronizeEventDefinitions(final String definitionName, final Event bpmnEvent, + final JsonArray dataList) { + + // find all named eventDefinitions for this event + Set<Element> eventDefinitions = bpmnEvent.getEventDefinitionsByType(definitionName); + + if (dataList == null && eventDefinitions.size() == 0) { + // no update needed at all + return eventDefinitions; + } + // If the size of the eventDefinition List is not equals the size of the + // dataList we add or remove eventDefinitions... + while ((dataList == null && eventDefinitions.size() > 0) + || (eventDefinitions.size() != dataList.size())) { try { - if (conditionalEventDefinitions.size() < dataList.size()) { - // add a new empty condition placeholder... - bpmnEvent.addEventDefinition("conditionalEventDefinition"); - } - if (conditionalEventDefinitions.size() > dataList.size()) { + if ((dataList == null && eventDefinitions.size() > 0) + || eventDefinitions.size() > dataList.size()) { // delete first condition from the list - Element definition = conditionalEventDefinitions.iterator().next(); + Element definition = eventDefinitions.iterator().next(); String id = definition.getAttribute("id"); bpmnEvent.deleteEventDefinition(id); + } else if (eventDefinitions.size() < dataList.size()) { + // add a new empty condition placeholder... + bpmnEvent.addEventDefinition(definitionName); } + } catch (BPMNModelException e) { logger.error("Failed to update BPMN Event Definition list: " + e.getMessage()); e.printStackTrace(); } // Update event definition list - conditionalEventDefinitions = bpmnEvent.getEventDefinitionsByType("conditionalEventDefinition"); - } - // now we can update the values one by one - // NOTE: the id can change within the definitionList if an element was deleted - // or moved! - // but we do not care about this issue. - Iterator<Element> iter = conditionalEventDefinitions.iterator(); - int i = 0; - while (iter.hasNext()) { - Element eventDefinitionElement = iter.next(); - JsonObject jsonData = dataList.getJsonObject(i); // .get(i); - if (jsonData != null) { - eventDefinitionElement.setAttribute("language", jsonData.getString("language", "")); - eventDefinitionElement.setAttribute("expression", jsonData.getString("expression", "")); - } - i++; - // update completed + eventDefinitions = bpmnEvent.getEventDefinitionsByType(definitionName); } + return eventDefinitions; } - - private void updateLinkEventDefinitions(final List<Element> eventDefinitions, final JsonArray dataList) { - // If the size of the conditionalDataList is not equals the size of the known - // eventConditionalDefinitions we print a warning - if (eventDefinitions.size() != dataList.size()) { - logger.warn("dataList does not match the EventDefinition list!"); - } - // just update the values one by one by referring to the signalRef id by - // comparing the name - for (int i = 0; i < eventDefinitions.size(); i++) { - Element eventDefinitionElement = eventDefinitions.get(i); - JsonObject jsonData = dataList.getJsonObject(i); // .get(i); - if (jsonData != null) { - eventDefinitionElement.setAttribute("name", jsonData.getString("name", "")); - eventDefinitionElement.setAttribute("target", jsonData.getString("target", "")); - } - // update completed - } - } - - /** - * Adds the ConditionalEvent definitions. Here we use a detail-control layout to - * have more flexibility designing the widgets. - * - * @param eventDefinitions - * @param dataBuilder - * @param schemaBuilder - * @param uiSchemaBuilder - */ - private void addConditionalEventDefinitions(final List<Element> eventDefinitions, final DataBuilder dataBuilder, - final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { - if (eventDefinitions.size() > 0) { - - JsonObject multilineOption = Json.createObjectBuilder() // - .add("multi", true).build(); - - uiSchemaBuilder. // - addCategory("Conditions"). // - addLayout(Layout.VERTICAL); - - // create a detail control Layout.... - JsonArrayBuilder controlsArrayBuilder = Json.createArrayBuilder(); - controlsArrayBuilder // - .add(Json.createObjectBuilder() // - .add("type", "Control") // - .add("scope", "#/properties/language"))// - .add(Json.createObjectBuilder() // - .add("type", "Control") // - .add("scope", "#/properties/expression") // - .add("label", "Expression") // - .add("options", multilineOption) // - ); - - JsonObjectBuilder detailLayoutBuilder = Json.createObjectBuilder(). // - add("type", "VerticalLayout"). /// - add("elements", controlsArrayBuilder); - - JsonObjectBuilder detailBuilder = Json.createObjectBuilder(). // - add("detail", detailLayoutBuilder.build()); - uiSchemaBuilder.addDetailLayout("conditions", "Conditions", detailBuilder.build()); - - /* - * Add the Schema .... - */ - schemaBuilder.addArray("conditions"); - schemaBuilder.addProperty("language", "string", null, null); - schemaBuilder.addProperty("expression", "string", null, null); - - /* - * Now we can create the data structure - each conditionalEventDefinition is - * represented as a separate object - */ - dataBuilder.addArray("conditions"); - for (Element definition : eventDefinitions) { - dataBuilder.addObject(); - dataBuilder.addData("language", definition.getAttribute("language")); - dataBuilder.addData("expression", definition.getAttribute("expression")); - } - } - } - - /** - * Adds the SignalEvent definitions - * <p> - * Note: Internally we need a mapping between the Signal name (Label) and the - * Signal id (value). As - * discussed here - * (https://jsonforms.discourse.group/t/how-to-separate-value-and-label-in-a-combobox/1200) - * we do not have this feature yet. Currently the efforts seems to be to high to - * implement a new - * renderer for JsonForms. - * - * @param eventDefinitions - * @param dataBuilder - * @param schemaBuilder - * @param uiSchemaBuilder - */ - private void addSignalEventDefinitions(final List<Element> eventDefinitions, final DataBuilder dataBuilder, - final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { - if (eventDefinitions.size() > 0) { - Map<String, String> arrayDetailOption = new HashMap<>(); - // GENERATED HorizontalLayout - arrayDetailOption.put("detail", "GENERATED"); - - uiSchemaBuilder. // - addCategory("Signals"). // - addLayout(Layout.VERTICAL); - uiSchemaBuilder.addElement("signals", "Signals", arrayDetailOption); - // uiSchemaBuilder.addElement("formalExpression", "Script", multilineOption); - - schemaBuilder.addArray("signals"); - - // find all signals in the current model and build an array... - Set<Signal> bpmnSignals = modelState.getBpmnModel().getSignals(); - String[] signalOptions = new String[bpmnSignals.size()]; - int i = 0; - for (Signal bpmnSignal : bpmnSignals) { - signalOptions[i] = bpmnSignal.getName(); - i++; - // signalOptions[i] = bpmnSignal.getId() + "|" + bpmnSignal.getName(); - } - schemaBuilder.addProperty("signal", "string", null, signalOptions); - // schemaBuilder.addPropertyOneOf("signal", "string", null, signalOptions); - - /* - * Now we can create the data structure - each signalEventDefinition is - * represented as a separate object. We resolve the signalRef - */ - dataBuilder.addArray("signals"); - for (Element definition : eventDefinitions) { - dataBuilder.addObject(); - String signalRefID = definition.getAttribute("signalRef"); - // fetch the corresponding Signal - Signal bpmnSignal = (Signal) modelState.getBpmnModel().findElementById(signalRefID); - if (bpmnSignal != null) { - dataBuilder.addData("signal", bpmnSignal.getName()); - } else { - logger.warn("invalid signalRefID found: " + signalRefID); - } - - } - } - - } - - /** - * Adds the LinkEvent definitions. - * <p> - * This is a simple detail section without custom layout. So we use - * detail=GERNERATED here. - * - * @param eventDefinitions - * @param dataBuilder - * @param schemaBuilder - * @param uiSchemaBuilder - */ - private void addLinkEventDefinitions(final List<Element> eventDefinitions, final DataBuilder dataBuilder, - final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { - if (eventDefinitions.size() > 0) { - Map<String, String> arrayDetailOption = new HashMap<>(); - // GENERATED HorizontalLayout - arrayDetailOption.put("detail", "GENERATED"); - - uiSchemaBuilder. // - addCategory("Link"). // - addLayout(Layout.VERTICAL); - uiSchemaBuilder.addElement("links", "Links", arrayDetailOption); - - schemaBuilder.addArray("links"); - schemaBuilder.addProperty("name", "string", null, null); - schemaBuilder.addProperty("target", "string", null, null); - - /* - * Now we can create the data structure - each conditionalEventDefinition is - * represented as a separate object - */ - dataBuilder.addArray("links"); - logger.warn(" addLinkEventDefinitions not yet implemented"); - for (Element definition : eventDefinitions) { - dataBuilder.addObject(); - dataBuilder.addData("name", definition.getAttribute("name")); - dataBuilder.addData("target", definition.getAttribute("target")); - } - } - - } - } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNGatewayExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNGatewayExtension.java index 24d28b8d..b7c1110b 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNGatewayExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNGatewayExtension.java @@ -17,26 +17,18 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.Set; import java.util.logging.Logger; import javax.json.JsonObject; import org.eclipse.glsp.graph.GModelElement; -import org.eclipse.glsp.graph.GNode; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Gateway; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.glsp.bpmn.LabelGNode; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; -import org.openbpmn.glsp.model.BPMNGModelState; -import org.openbpmn.glsp.utils.BPMNGraphUtil; - -import com.google.inject.Inject; /** * This is the Default BPMNEvent extension providing the JSONForms shemata. @@ -49,9 +41,6 @@ public class DefaultBPMNGatewayExtension extends AbstractBPMNElementExtension { @SuppressWarnings("unused") private static Logger logger = Logger.getLogger(DefaultBPMNGatewayExtension.class.getName()); - @Inject - protected BPMNGModelState modelState; - public DefaultBPMNGatewayExtension() { super(); } @@ -106,42 +95,16 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Update the Gateway Properties + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("name".equals(feature)) { - String text = json.getString(feature); - bpmnElement.setName(text); - // Update Label... - Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); - if (!label.isEmpty()) { - LabelGNode lgn = (LabelGNode) label.get(); - // update the bpmn-text-node of the GNodeElement - GNode gnode = BPMNGraphUtil.findMultiLineTextNode(lgn); - if (gnode != null) { - gnode.getArgs().put("text", text); - } - continue; - } - - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - - if ("gatewaydirection".equals(feature)) { - bpmnElement.setAttribute("gatewayDirection", json.getString(feature)); - continue; - } - // TODO implement Event features - } - + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); + bpmnElement.setAttribute("gatewayDirection", json.getString("gatewaydirection")); } - } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNMessageExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNMessageExtension.java index 2f3665fa..fdfd85f2 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNMessageExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNMessageExtension.java @@ -17,24 +17,18 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.Set; import javax.json.JsonObject; import org.eclipse.glsp.graph.GModelElement; -import org.eclipse.glsp.graph.GNode; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Message; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.bpmn.elements.core.BPMNElementNode; -import org.openbpmn.glsp.bpmn.LabelGNode; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; import org.openbpmn.glsp.model.BPMNGModelState; -import org.openbpmn.glsp.utils.BPMNGraphUtil; import com.google.inject.Inject; @@ -94,37 +88,14 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Update the Message default properties + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - - // default update of name and documentation - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("name".equals(feature)) { - String text = json.getString(feature); - bpmnElement.setName(text); - // Update GModelElement Label... - Optional<GModelElement> label = modelState.getIndex().get(gNodeElement.getId() + "_bpmnlabel"); - if (!label.isEmpty()) { - LabelGNode lgn = (LabelGNode) label.get(); - // update the bpmn-text-node of the GNodeElement - GNode gnode = BPMNGraphUtil.findMultiLineTextNode(lgn); - if (gnode != null) { - gnode.getArgs().put("text", text); - } - continue; - } - continue; - } - if ("documentation".equals(feature)) { - ((BPMNElementNode) bpmnElement).setDocumentation(json.getString(feature)); - continue; - } - - } - + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); } - } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNParticipantExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNParticipantExtension.java index 332f94a7..b42c3698 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNParticipantExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNParticipantExtension.java @@ -20,7 +20,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import javax.json.Json; import javax.json.JsonArray; @@ -120,68 +119,57 @@ public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnEl Participant participant = (Participant) bpmnElement; try { BPMNProcess process = modelState.getBpmnModel().openProcess(participant.getProcessRef()); - // check custom features - Set<String> features = json.keySet(); - for (String feature : features) { - if ("name".equals(feature)) { - bpmnElement.setName(json.getString(feature)); - process.setName(json.getString(feature)); - // Update Label... - ((BPMNGNode) gNodeElement).setName(json.getString(feature)); - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - // LaneSet... - if ("lanes".equals(feature)) { - List<String> laneDataIDs = new ArrayList<>(); // collect remaining lanes - logger.debug("...update feature = " + feature); - JsonArray laneSetValues = json.getJsonArray(feature); - for (JsonValue laneValue : laneSetValues) { - // update lane properties - JsonObject laneData = (JsonObject) laneValue; - if (laneData.get("id") != null) { - String id = laneData.getJsonString("id").getString(); - // String id = jsonID.toString(); - laneDataIDs.add(id); - Lane bpmnLane = process.findLaneById(id); - if (bpmnLane != null) { - bpmnLane.setName(laneData.getString("name")); - bpmnLane.setDocumentation(laneData.getString("documentation")); - // update gnode... - Optional<GModelElement> _gLane = modelState.getIndex().get(bpmnLane.getId()); - if (_gLane.isPresent()) { - LaneGNode gLane = (LaneGNode) _gLane.get(); - gLane.setName(laneData.getString("name")); - } - } - } else { - // this is a new lane - construct the lane in the BPMN model first.. - Lane bpmnLane = process.addLane("Lane " + (process.getLanes().size() + 1)); - laneDataIDs.add(bpmnLane.getId()); - modelState.reset(); - } - } - // now we need to delete all lanes no longer part of the laneSetValues - // We need two loops here to avoid concurrency exceptions! - List<String> laneIDsToBeRemoved = new ArrayList<>(); - for (Lane bpmnLane : process.getLanes()) { - if (bpmnLane != null && !laneDataIDs.contains(bpmnLane.getId())) { - laneIDsToBeRemoved.add(bpmnLane.getId()); - } - } - if (laneIDsToBeRemoved.size() > 0) { - modelState.reset(); - for (String lid : laneIDsToBeRemoved) { - // lane was removed, so remove the lane form the process too - process.deleteLane(lid); + bpmnElement.setName(json.getString("name", "")); + process.setName(json.getString("name", "")); + ((BPMNGNode) gNodeElement).setName(json.getString("name", "")); + bpmnElement.setDocumentation(json.getString("documentation")); + + // LaneSet... + List<String> laneDataIDs = new ArrayList<>(); // collect remaining lanes + logger.debug("...update feature = " + "lanes"); + JsonArray laneSetValues = json.getJsonArray("lanes"); + for (JsonValue laneValue : laneSetValues) { + // update lane properties + JsonObject laneData = (JsonObject) laneValue; + if (laneData.get("id") != null) { + String id = laneData.getJsonString("id").getString(); + // String id = jsonID.toString(); + laneDataIDs.add(id); + Lane bpmnLane = process.findLaneById(id); + if (bpmnLane != null) { + bpmnLane.setName(laneData.getString("name")); + bpmnLane.setDocumentation(laneData.getString("documentation")); + // update gnode... + Optional<GModelElement> _gLane = modelState.getIndex().get(bpmnLane.getId()); + if (_gLane.isPresent()) { + LaneGNode gLane = (LaneGNode) _gLane.get(); + gLane.setName(laneData.getString("name")); } } + } else { + // this is a new lane - construct the lane in the BPMN model first.. + Lane bpmnLane = process.addLane("Lane " + (process.getLanes().size() + 1)); + laneDataIDs.add(bpmnLane.getId()); + modelState.reset(); } } + // now we need to delete all lanes no longer part of the laneSetValues + // We need two loops here to avoid concurrency exceptions! + List<String> laneIDsToBeRemoved = new ArrayList<>(); + for (Lane bpmnLane : process.getLanes()) { + if (bpmnLane != null && !laneDataIDs.contains(bpmnLane.getId())) { + laneIDsToBeRemoved.add(bpmnLane.getId()); + } + } + if (laneIDsToBeRemoved.size() > 0) { + modelState.reset(); + for (String lid : laneIDsToBeRemoved) { + // lane was removed, so remove the lane form the process too + process.deleteLane(lid); + } + } + } catch (BPMNModelException e) { logger.error("Failed to update laneSet properties: " + e.getMessage()); } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNSequenceFlowExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNSequenceFlowExtension.java index 7962b8ae..2e28e9d9 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNSequenceFlowExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNSequenceFlowExtension.java @@ -102,11 +102,10 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } dataBuilder // .addData("conditionExpression", conditionalExpression) // - .addData("Default", "test"); + ; schemaBuilder. // - addProperty("conditionExpression", "string", description). // - addProperty("default", "boolean", null); + addProperty("conditionExpression", "string", description); // Map<String, String> multilineOption = new HashMap<>(); multilineOption.put("multi", "true"); diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTaskExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTaskExtension.java index 0a90949d..25e6e2db 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTaskExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTaskExtension.java @@ -17,23 +17,20 @@ import java.util.HashMap; import java.util.Map; -import java.util.Set; import javax.json.JsonObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.glsp.graph.GModelElement; -import org.eclipse.glsp.graph.GNode; +import org.openbpmn.bpmn.BPMNNS; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Activity; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.glsp.bpmn.BPMNGNode; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; -import org.openbpmn.glsp.utils.BPMNGraphUtil; /** * This is the Default BPMNEvent extension providing the JSONForms shemata. @@ -95,7 +92,8 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder if (BPMNTypes.SCRIPT_TASK.equals(taskElement.getType())) { dataBuilder // .addData("scriptformat", taskElement.getAttribute("scriptFormat")) // - .addData("script", taskElement.getChildNodeContent("script")); + .addData("script", taskElement + .getChildNodeContent(BPMNNS.BPMN2, "script")); schemaBuilder. // addProperty("scriptformat", "string", "Format of the script"). // @@ -112,42 +110,18 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Update the default activity properties. + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - // default update of name and documentation - - Set<String> features = json.keySet(); - for (String feature : features) { - if ("name".equals(feature)) { - String text = json.getString(feature); - bpmnElement.setName(text); - // update the bpmn-text-node of the GNodeElement - GNode gnode = BPMNGraphUtil.findMultiLineTextNode((BPMNGNode) gNodeElement); - if (gnode != null) { - gnode.getArgs().put("text", text); - } - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - - logger.debug("...update feature = " + feature); - - if ("scriptformat".equals(feature)) { - bpmnElement.setAttribute("scriptFormat", json.getString(feature)); - continue; - } - - if ("script".equals(feature)) { - bpmnElement.setChildNodeContent("script", json.getString(feature)); - continue; - } - } - + updateNameProperty(json, bpmnElement, gNodeElement); + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); + bpmnElement.setAttribute("scriptFormat", json.getString("scriptformat")); + bpmnElement.setChildNodeContent(BPMNNS.BPMN2, "script", json.getString("script"), true); } } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTextAnnotationExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTextAnnotationExtension.java index fa72a732..e4736651 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTextAnnotationExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/DefaultBPMNTextAnnotationExtension.java @@ -18,7 +18,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.Set; import javax.json.JsonObject; @@ -76,11 +75,6 @@ public boolean handlesBPMNElement(final BPMNElement bpmnElement) { public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder dataBuilder, final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { - if (!(bpmnElement instanceof TextAnnotation)) { - logger.warn("invalid BPMN element - TextAnnotation expected!"); - return; - } - String text = ((TextAnnotation) bpmnElement).getText(); dataBuilder // @@ -104,40 +98,25 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder } + /** + * Updates the textAnnotation properties + */ @Override public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, final GModelElement gNodeElement) { - if (!(bpmnElement instanceof TextAnnotation)) { - logger.warn("invalid BPMN element - TextAnnotation expected!"); - return; + // update attributes and tags + bpmnElement.setDocumentation(json.getString("documentation")); + bpmnElement.setAttribute("textFormat", json.getString("textFormat")); + + // Update the text property + String text = json.getString("text", ""); + ((TextAnnotation) bpmnElement).setText(text); + // Update GModelElement Text Node... + Optional<GModelElement> textNode = modelState.getIndex().get(gNodeElement.getId() + "_bpmntext"); + if (!textNode.isEmpty()) { + textNode.get().getArgs().put("text", text); } - - // default update of name and documentation - Set<String> features = json.keySet(); - for (String feature : features) { - - if ("textFormat".equals(feature)) { - bpmnElement.setAttribute("textFormat", json.getString(feature)); - continue; - } - if ("text".equals(feature)) { - String text = json.getString(feature); - ((TextAnnotation) bpmnElement).setText(text); - // Update GModelElement Text Node... - Optional<GModelElement> textNode = modelState.getIndex().get(gNodeElement.getId() + "_bpmntext"); - if (!textNode.isEmpty()) { - textNode.get().getArgs().put("text", text); - } - continue; - } - if ("documentation".equals(feature)) { - bpmnElement.setDocumentation(json.getString(feature)); - continue; - } - - } - } } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/LinkEventDefinitionExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/LinkEventDefinitionExtension.java new file mode 100644 index 00000000..c2da834e --- /dev/null +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/LinkEventDefinitionExtension.java @@ -0,0 +1,143 @@ +/******************************************************************************** + * Copyright (c) 2022 Imixs Software Solutions GmbH and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.openbpmn.extension; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.json.JsonArray; +import javax.json.JsonObject; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.glsp.graph.GModelElement; +import org.openbpmn.bpmn.BPMNTypes; +import org.openbpmn.bpmn.elements.Event; +import org.openbpmn.bpmn.elements.core.BPMNElement; +import org.openbpmn.glsp.jsonforms.DataBuilder; +import org.openbpmn.glsp.jsonforms.SchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; +import org.w3c.dom.Element; + +/** + * The LinkEventDefinitionExtension is responsible to read and update optional + * LinkEventDefinitions from the BPMN model. The Extension builds a custom + * property section named 'Link Definitions' shown a list of all + * LinkEventDefinitions + * define in a Event. + * + * @author rsoika + */ +public class LinkEventDefinitionExtension extends DefaultBPMNEventExtension { + + private static Logger logger = LogManager.getLogger(DefaultBPMNSequenceFlowExtension.class); + + @Override + public int getPriority() { + return 102; + } + + /** + * Returns if this Extension can be applied to the given elementTypeID + */ + @Override + public boolean handlesElementTypeId(final String elementTypeId) { + return BPMNTypes.BPMN_EVENTS.contains(elementTypeId); + } + + /** + * This Helper Method generates a JSON Object with the BPMNElement properties. + * <p> + * This json object is used on the GLSP Client to generate the EMF JsonForms + */ + @Override + public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder dataBuilder, + final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { + + Event event = (Event) bpmnElement; + + // Conditional + + Set<Element> linkEventDefinitions = event.getEventDefinitionsByType("linkEventDefinition"); + + if (linkEventDefinitions.size() > 0) { + + Map<String, String> arrayDetailOption = new HashMap<>(); + // GENERATED HorizontalLayout + arrayDetailOption.put("detail", "GENERATED"); + + uiSchemaBuilder. // + addCategory("Link"). // + addLayout(Layout.VERTICAL); + uiSchemaBuilder.addElement("links", "Links", arrayDetailOption); + + schemaBuilder.addArray("links"); + schemaBuilder.addProperty("name", "string", null, null); + schemaBuilder.addProperty("target", "string", null, null); + + /* + * Now we can create the data structure - each conditionalEventDefinition is + * represented as a separate object + */ + dataBuilder.addArray("links"); + logger.warn(" addLinkEventDefinitions not yet implemented"); + for (Element definition : linkEventDefinitions) { + dataBuilder.addObject(); + dataBuilder.addData("name", definition.getAttribute("name")); + dataBuilder.addData("target", definition.getAttribute("target")); + } + + } + } + + /** + * Update the link definitions + * + * This method updates all linkEventDefinitions. The method expects a + * dataList containing all link definitions with its values. + * The method simply overwrites all linkEventDefinitions. + * <p> + * + */ + @Override + public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, + final GModelElement gNodeElement) { + Event bpmnEvent = (Event) bpmnElement; + JsonArray dataList = json.getJsonArray("links"); + + // synchronize the definition list of the event element + Set<Element> linkEventDefinitions = synchronizeEventDefinitions("linkEventDefinition", bpmnEvent, + dataList); + + // just update the values one by one by referring to the signalRef id by + // comparing the name + Iterator<Element> iter = linkEventDefinitions.iterator(); + int i = 0; + while (iter.hasNext()) { + Element eventDefinitionElement = iter.next(); + JsonObject jsonData = dataList.getJsonObject(i); // .get(i); + if (jsonData != null) { + eventDefinitionElement.setAttribute("name", jsonData.getString("name", "")); + eventDefinitionElement.setAttribute("target", jsonData.getString("target", "")); + } + // update completed + } + + } +} diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/SignalEventDefinitionExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/SignalEventDefinitionExtension.java new file mode 100644 index 00000000..a47296a8 --- /dev/null +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/SignalEventDefinitionExtension.java @@ -0,0 +1,187 @@ +/******************************************************************************** + * Copyright (c) 2022 Imixs Software Solutions GmbH and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ +package org.openbpmn.extension; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.json.JsonArray; +import javax.json.JsonObject; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.glsp.graph.GModelElement; +import org.openbpmn.bpmn.BPMNTypes; +import org.openbpmn.bpmn.elements.Event; +import org.openbpmn.bpmn.elements.Signal; +import org.openbpmn.bpmn.elements.core.BPMNElement; +import org.openbpmn.bpmn.exceptions.BPMNInvalidReferenceException; +import org.openbpmn.bpmn.exceptions.BPMNInvalidTypeException; +import org.openbpmn.bpmn.exceptions.BPMNMissingElementException; +import org.openbpmn.glsp.jsonforms.DataBuilder; +import org.openbpmn.glsp.jsonforms.SchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder; +import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; +import org.w3c.dom.Element; + +/** + * The LinkEventDefinitionExtension is responsible to read and update optional + * LinkEventDefinitions from the BPMN model. The Extension builds a custom + * property section named 'Link Definitions' shown a list of all + * LinkEventDefinitions + * define in a Event. + * + * @author rsoika + */ +public class SignalEventDefinitionExtension extends DefaultBPMNEventExtension { + + private static Logger logger = LogManager.getLogger(DefaultBPMNSequenceFlowExtension.class); + + @Override + public int getPriority() { + return 103; + } + + /** + * Returns if this Extension can be applied to the given elementTypeID + */ + @Override + public boolean handlesElementTypeId(final String elementTypeId) { + return BPMNTypes.BPMN_EVENTS.contains(elementTypeId); + } + + /** + * Adds the SignalEvent definitions + * <p> + * Note: Internally we need a mapping between the Signal name (Label) and the + * Signal id (value). As + * discussed here + * (https://jsonforms.discourse.group/t/how-to-separate-value-and-label-in-a-combobox/1200) + * we do not have this feature yet. Currently the efforts seems to be to high to + * implement a new + * renderer for JsonForms. + */ + @Override + public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder dataBuilder, + final SchemaBuilder schemaBuilder, final UISchemaBuilder uiSchemaBuilder) { + + Event event = (Event) bpmnElement; + + // Conditional + + Set<Element> signalEventDefinitions = event.getEventDefinitionsByType("signalEventDefinition"); + + if (signalEventDefinitions.size() > 0) { + Map<String, String> arrayDetailOption = new HashMap<>(); + // GENERATED HorizontalLayout + arrayDetailOption.put("detail", "GENERATED"); + + uiSchemaBuilder. // + addCategory("Signals"). // + addLayout(Layout.VERTICAL); + uiSchemaBuilder.addElement("signals", "Signals", arrayDetailOption); + // uiSchemaBuilder.addElement("formalExpression", "Script", multilineOption); + + schemaBuilder.addArray("signals"); + + // find all signals in the current model and build an array... + Set<Signal> bpmnSignals = modelState.getBpmnModel().getSignals(); + String[] signalOptions = new String[bpmnSignals.size()]; + int i = 0; + for (Signal bpmnSignal : bpmnSignals) { + signalOptions[i] = bpmnSignal.getName(); + i++; + // signalOptions[i] = bpmnSignal.getId() + "|" + bpmnSignal.getName(); + } + schemaBuilder.addProperty("signal", "string", null, signalOptions); + // schemaBuilder.addPropertyOneOf("signal", "string", null, signalOptions); + + /* + * Now we can create the data structure - each signalEventDefinition is + * represented as a separate object. We resolve the signalRef + */ + dataBuilder.addArray("signals"); + for (Element definition : signalEventDefinitions) { + dataBuilder.addObject(); + String signalRefID = definition.getAttribute("signalRef"); + // fetch the corresponding Signal + Signal bpmnSignal = (Signal) modelState.getBpmnModel().findElementById(signalRefID); + if (bpmnSignal != null) { + dataBuilder.addData("signal", bpmnSignal.getName()); + } else { + logger.warn("invalid signalRefID found: " + signalRefID); + } + + } + } + + } + + /** + * This method updates the signalEventDefinitions. The method expects a + * dataList containing all conditions with its values (including the id). + * The method simply overwrites all csignalEventDefinitions. + * + * @See addSignalEventDefinitions how we map between the signal name and its id. + * + */ + @Override + public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, + final GModelElement gNodeElement) { + Event bpmnEvent = (Event) bpmnElement; + JsonArray dataList = json.getJsonArray("links"); + + // synchronize the definition list of the event element + Set<Element> signalEventDefinitions = synchronizeEventDefinitions("signalEventDefinition", bpmnEvent, dataList); + + // now we can update the values one by referring to the signalRef id by + // comparing the name + Iterator<Element> iter = signalEventDefinitions.iterator(); + int i = 0; + while (iter.hasNext()) { + Element eventDefinitionElement = iter.next(); + JsonObject jsonData = dataList.getJsonObject(i); // .get(i); + if (jsonData != null) { + + String signalName = ""; + + try { + signalName = jsonData.getString("signal"); + } catch (NullPointerException en) { + // no name defined! + } + logger.debug("signal=" + signalName); + try { + // fetch the signal from teh Model Signal list by name... + Signal signal = modelState.getBpmnModel().findSignalByName(signalName); + if (signal != null) { + eventDefinitionElement.setAttribute("signalRef", signal.getId()); + } else { + // no signal defintion found - delete signalRef... + eventDefinitionElement.setAttribute("signalRef", ""); + } + } catch (BPMNInvalidReferenceException | BPMNMissingElementException | BPMNInvalidTypeException e) { + e.printStackTrace(); + } + } + i++; + // update completed + } + + } +} diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/TimerEventDefinitionExtension.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/TimerEventDefinitionExtension.java index 39d80c98..5fe850f8 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/TimerEventDefinitionExtension.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/extension/TimerEventDefinitionExtension.java @@ -27,12 +27,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.glsp.graph.GModelElement; -import org.openbpmn.bpmn.BPMNModel; import org.openbpmn.bpmn.BPMNNS; import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Event; import org.openbpmn.bpmn.elements.core.BPMNElement; -import org.openbpmn.bpmn.exceptions.BPMNModelException; import org.openbpmn.glsp.jsonforms.DataBuilder; import org.openbpmn.glsp.jsonforms.SchemaBuilder; import org.openbpmn.glsp.jsonforms.UISchemaBuilder; @@ -50,9 +48,8 @@ * * @author rsoika */ -public class TimerEventDefinitionExtension extends AbstractBPMNElementExtension { +public class TimerEventDefinitionExtension extends DefaultBPMNEventExtension { - @SuppressWarnings("unused") private static Logger logger = LogManager.getLogger(DefaultBPMNSequenceFlowExtension.class); @Inject @@ -64,7 +61,7 @@ public TimerEventDefinitionExtension() { @Override public int getPriority() { - return 100; // below default settings from Edge element + return 104; // below default settings from Edge element } /** @@ -144,14 +141,10 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder for (Element timerDefinition : linkEventDefinitions) { dataBuilder.addObject(); // test the type of the timer object.... - Element timeDuration = BPMNModel.findChildNodeByName(timerDefinition, - event.getBpmnProcess().getModel().getPrefix(BPMNNS.BPMN2) + ":timeDuration"); - - Element timeCycle = BPMNModel.findChildNodeByName(timerDefinition, - event.getBpmnProcess().getModel().getPrefix(BPMNNS.BPMN2) + ":timeCycle"); - - Element timeDate = BPMNModel.findChildNodeByName(timerDefinition, - event.getBpmnProcess().getModel().getPrefix(BPMNNS.BPMN2) + ":timeDate"); + Element timeDuration = event.getModel().findChildNodeByName(timerDefinition, BPMNNS.BPMN2, + "timeDuration"); + Element timeCycle = event.getModel().findChildNodeByName(timerDefinition, BPMNNS.BPMN2, "timeCycle"); + Element timeDate = event.getModel().findChildNodeByName(timerDefinition, BPMNNS.BPMN2, "timeDate"); String timerValue = ""; String timerType = "Time/Date"; // default @@ -175,26 +168,7 @@ public void buildPropertiesForm(final BPMNElement bpmnElement, final DataBuilder /** * Update the timers definitions - */ - @Override - public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, - final GModelElement gNodeElement) { - - Event bpmnEvent = (Event) bpmnElement; - Set<String> features = json.keySet(); - for (String feature : features) { - - // Update eventDefinitions for each definition type... - Set<Element> eventDefinitions = bpmnEvent.getEventDefinitions(); - if ("timers".equals(feature)) { - JsonArray dataList = json.getJsonArray("timers"); - updateTimerEventDefinitions(bpmnEvent, dataList); - } - - } - } - - /** + * * This method updates all timerEventDefinitions. The method expects a * dataList containing all timer definitions with its values. * The method simply overwrites all timerEventDefinitions. @@ -212,34 +186,15 @@ public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnEl * </bpmn2:startEvent> * } * </pre> - * - * @param bpmnEvent - * @param dataList */ - private void updateTimerEventDefinitions(final Event bpmnEvent, final JsonArray dataList) { - // find all conditionalEventDefinitions for this event - Set<Element> timerEventDefinitions = bpmnEvent.getEventDefinitionsByType("timerEventDefinition"); - // If the size of the DataList is not equals the size of the - // DefinitionList we add or remove definitions... - while (timerEventDefinitions.size() != dataList.size()) { - try { - if (timerEventDefinitions.size() < dataList.size()) { - // add a new empty condition placeholder... - bpmnEvent.addEventDefinition("timerEventDefinition"); - } - if (timerEventDefinitions.size() > dataList.size()) { - // delete first condition from the list - Element definition = timerEventDefinitions.iterator().next(); - String id = definition.getAttribute("id"); - bpmnEvent.deleteEventDefinition(id); - } - } catch (BPMNModelException e) { - logger.error("Failed to update BPMN Event Definition list: " + e.getMessage()); - e.printStackTrace(); - } - // Update event definition list - timerEventDefinitions = bpmnEvent.getEventDefinitionsByType("timerEventDefinition"); - } + @Override + public void updatePropertiesData(final JsonObject json, final BPMNElement bpmnElement, + final GModelElement gNodeElement) { + Event bpmnEvent = (Event) bpmnElement; + JsonArray dataList = json.getJsonArray("timers"); + + // synchronize the definition list of the event element + Set<Element> timerEventDefinitions = synchronizeEventDefinitions("timerEventDefinition", bpmnEvent, dataList); // now we can update the values one by one // NOTE: the id can change within the definitionList if an element was deleted diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/BPMNDiagramModule.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/BPMNDiagramModule.java index c6414a55..b814acf1 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/BPMNDiagramModule.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/BPMNDiagramModule.java @@ -32,6 +32,7 @@ import org.eclipse.glsp.server.operations.OperationHandler; import org.openbpmn.extension.BPMNCreateExtensionHandler; import org.openbpmn.extension.BPMNExtension; +import org.openbpmn.extension.ConditionalEventDefinitionExtension; import org.openbpmn.extension.DefaultBPMNDataObjectExtension; import org.openbpmn.extension.DefaultBPMNDefinitionsExtension; import org.openbpmn.extension.DefaultBPMNEdgeExtension; @@ -42,6 +43,8 @@ import org.openbpmn.extension.DefaultBPMNSequenceFlowExtension; import org.openbpmn.extension.DefaultBPMNTaskExtension; import org.openbpmn.extension.DefaultBPMNTextAnnotationExtension; +import org.openbpmn.extension.LinkEventDefinitionExtension; +import org.openbpmn.extension.SignalEventDefinitionExtension; import org.openbpmn.extension.TimerEventDefinitionExtension; import org.openbpmn.glsp.elements.data.BPMNApplyEditLabelOperationHandler; import org.openbpmn.glsp.elements.data.BPMNCreateDataObjectHandler; @@ -232,6 +235,9 @@ public void configureBPMNExtensions(final Multibinder<BPMNExtension> binding) { binding.addBinding().to(DefaultBPMNEdgeExtension.class); binding.addBinding().to(DefaultBPMNSequenceFlowExtension.class); binding.addBinding().to(TimerEventDefinitionExtension.class); + binding.addBinding().to(SignalEventDefinitionExtension.class); + binding.addBinding().to(ConditionalEventDefinitionExtension.class); + binding.addBinding().to(LinkEventDefinitionExtension.class); } } diff --git a/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/model/BPMNGModelFactory.java b/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/model/BPMNGModelFactory.java index 12cbb498..5b76ec0a 100644 --- a/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/model/BPMNGModelFactory.java +++ b/open-bpmn.glsp-server/src/main/java/org/openbpmn/glsp/model/BPMNGModelFactory.java @@ -20,6 +20,8 @@ import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -264,7 +266,14 @@ void applyBPMNExtensions(final GModelElement elementNode, final BPMNElement bpmn * extensions we also add a CSS class */ if (extensions != null) { - for (BPMNExtension extension : extensions) { + + // sort extensions by priority + List<BPMNExtension> sortedExtensions = new ArrayList<>(); + sortedExtensions.addAll(extensions); + Comparator<BPMNExtension> byPriority = Comparator.comparing(BPMNExtension::getPriority); + Collections.sort(sortedExtensions, byPriority); + + for (BPMNExtension extension : sortedExtensions) { // validate if the extension can handle this BPMN element if (extension.handlesBPMNElement(bpmnElement)) { // add JSONForms Schemata diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElement.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElement.java index b6b71e68..8209c59d 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElement.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/elements/core/BPMNElement.java @@ -277,7 +277,8 @@ public String getAttribute(String name) { } /** - * Set the value of a given attribute by name. + * Set the value of a given attribute by name. If the value is null, the + * attribute will be removed. * <p> * The method operates directly on the attriubteMap loaded in the constructor. * @@ -288,9 +289,12 @@ public void setAttribute(String name, String value) { if (name == null || name.isEmpty() || attributeMap == null) { return; } - // if we did not found the attribute, we add a new one... - this.getElementNode().setAttribute(name, value); - + // if the value is null we remove the attibute + if (value == null) { + this.getElementNode().removeAttribute(name); + } else { + this.getElementNode().setAttribute(name, value); + } } /**