forked from imixs/open-bpmn
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new TimerEventDefinitionExtension
Issue imixs#177
- Loading branch information
Showing
7 changed files
with
524 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.openbpmn" exporterVersion="1.0.0" targetNamespace="http://org.openbpmn"> | ||
<bpmn2:process id="process_1" name="Default Process" processType="Public"> | ||
<bpmn2:documentation id="documentation_irBnnQ"/> | ||
<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:timerEventDefinition id="timerEventDefinition_dFC6Sg"> | ||
<bpmn2:timeCycle id="FormalExpression_1" xsi:type="bpmn2:tFormalExpression">2bx</bpmn2:timeCycle> | ||
</bpmn2:timerEventDefinition> | ||
<bpmn2:timerEventDefinition id="timerEventDefinition_peWH9A"> | ||
<bpmn2:timeDate id="FormalExpression_2" xsi:type="bpmn2:tFormalExpression">1ay</bpmn2:timeDate> | ||
</bpmn2:timerEventDefinition> | ||
</bpmn2:startEvent> | ||
</bpmn2:process> | ||
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="OpenBPMN Diagram"> | ||
<bpmndi:BPMNPlane bpmnElement="process_1" id="BPMNPlane_1"> | ||
<bpmndi:BPMNShape bpmnElement="event_n8bj0g" id="BPMNShape_KvjEBA"> | ||
<dc:Bounds height="36.0" width="36.0" x="90.0" y="54.0"/> | ||
<bpmndi:BPMNLabel id="BPMNLabel_HFenEA"> | ||
<dc:Bounds height="16.0" width="100.0" x="58.0" y="90.0"/> | ||
</bpmndi:BPMNLabel> | ||
</bpmndi:BPMNShape> | ||
</bpmndi:BPMNPlane> | ||
</bpmndi:BPMNDiagram> | ||
</bpmn2:definitions> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
285 changes: 285 additions & 0 deletions
285
...-bpmn.glsp-server/src/main/java/org/openbpmn/extension/TimerEventDefinitionExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
/******************************************************************************** | ||
* 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.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; | ||
import org.openbpmn.glsp.jsonforms.UISchemaBuilder.Layout; | ||
import org.openbpmn.glsp.model.BPMNGModelState; | ||
import org.w3c.dom.Element; | ||
|
||
import com.google.inject.Inject; | ||
|
||
/** | ||
* 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 TimerEventDefinitionExtension extends AbstractBPMNElementExtension { | ||
|
||
@SuppressWarnings("unused") | ||
private static Logger logger = LogManager.getLogger(DefaultBPMNSequenceFlowExtension.class); | ||
|
||
@Inject | ||
protected BPMNGModelState modelState; | ||
|
||
public TimerEventDefinitionExtension() { | ||
super(); | ||
} | ||
|
||
@Override | ||
public int getPriority() { | ||
return 100; // below default settings from Edge element | ||
} | ||
|
||
/** | ||
* 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 Extension is for BPMNEvents only | ||
*/ | ||
@Override | ||
public boolean handlesBPMNElement(final BPMNElement bpmnElement) { | ||
return (bpmnElement instanceof Event); | ||
} | ||
|
||
/** | ||
* 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; | ||
|
||
// Link | ||
Set<Element> linkEventDefinitions = event.getEventDefinitionsByType("timerEventDefinition"); | ||
|
||
if (linkEventDefinitions.size() > 0) { | ||
/****************************** | ||
* Create UISchema | ||
******************************/ | ||
final JsonObject radioOption = Json.createObjectBuilder() // | ||
.add("format", "radio").build(); | ||
uiSchemaBuilder. // | ||
addCategory("Timer Definitions"). // | ||
addLayout(Layout.VERTICAL); | ||
// create a detail control Layout.... | ||
JsonArrayBuilder controlsArrayBuilder = Json.createArrayBuilder(); | ||
controlsArrayBuilder // | ||
.add(Json.createObjectBuilder() // | ||
.add("type", "Control") // | ||
.add("scope", "#/properties/type") // | ||
.add("options", radioOption) // | ||
) // | ||
.add(Json.createObjectBuilder() // | ||
.add("type", "Control") // | ||
.add("scope", "#/properties/value") // | ||
.add("label", "Value") // | ||
); | ||
JsonObjectBuilder detailLayoutBuilder = Json.createObjectBuilder(). // | ||
add("type", "HorizontalLayout"). /// | ||
add("elements", controlsArrayBuilder); | ||
JsonObjectBuilder detailBuilder = Json.createObjectBuilder(). // | ||
add("detail", detailLayoutBuilder.build()); | ||
uiSchemaBuilder.addDetailLayout("timers", "Timer Definition", detailBuilder.build()); | ||
|
||
/*************************** | ||
* Create schemaBuilder | ||
***************************/ | ||
String[] timerTypes = { "Time/Date", "Interval", "Duration" }; | ||
schemaBuilder.addArray("timers"); | ||
schemaBuilder.addProperty("type", "string", null, timerTypes); | ||
schemaBuilder.addProperty("value", "string", null, null); | ||
|
||
/************************** | ||
* Create DataBuilder | ||
* | ||
* Each timerDefinition is represented as a separate object | ||
**************************/ | ||
dataBuilder.addArray("timers"); | ||
|
||
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"); | ||
|
||
String timerValue = ""; | ||
String timerType = "Time/Date"; // default | ||
if (timeDate != null) { | ||
timerType = "Time/Date"; | ||
timerValue = timeDate.getTextContent(); | ||
} | ||
if (timeDuration != null) { | ||
timerType = "Duration"; | ||
timerValue = timeDuration.getTextContent(); | ||
} | ||
if (timeCycle != null) { | ||
timerType = "Interval"; | ||
timerValue = timeCycle.getTextContent(); | ||
} | ||
dataBuilder.addData("type", timerType); | ||
dataBuilder.addData("value", timerValue); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 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. | ||
* <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> | ||
* | ||
* @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"); | ||
} | ||
|
||
// 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 = timerEventDefinitions.iterator(); | ||
int i = 0; | ||
while (iter.hasNext()) { | ||
Element eventDefinitionElement = iter.next(); | ||
JsonObject jsonData = dataList.getJsonObject(i); // .get(i); | ||
if (jsonData != null) { | ||
// remove the old child elements | ||
while (eventDefinitionElement.hasChildNodes()) { | ||
eventDefinitionElement.removeChild(eventDefinitionElement.getFirstChild()); | ||
} | ||
// depending on the type we need to create a new child element | ||
Element timerObject = null; | ||
// { "Time/Date", "Interval", "Duration" }; | ||
String timerType = jsonData.getString("type", "Time/Date"); | ||
if ("Time/Date".equals(timerType)) { | ||
timerObject = bpmnEvent.getModel().createElement(BPMNNS.BPMN2, "timeDate"); | ||
} | ||
if ("Duration".equals(timerType)) { | ||
timerObject = bpmnEvent.getModel().createElement(BPMNNS.BPMN2, "timeDuration"); | ||
} | ||
if ("Interval".equals(timerType)) { | ||
timerObject = bpmnEvent.getModel().createElement(BPMNNS.BPMN2, "timeCycle"); | ||
|
||
} | ||
|
||
// xsi:type="bpmn2:tFormalExpression" id="FormalExpression_1" | ||
timerObject.setAttribute("xsi:type", "bpmn2:tFormalExpression"); | ||
timerObject.setAttribute("id", "FormalExpression_" + i); | ||
timerObject.setTextContent(jsonData.getString("value", "")); | ||
|
||
// finally add the new updated timerObject | ||
eventDefinitionElement.appendChild(timerObject); | ||
|
||
} | ||
i++; | ||
// update completed | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.