Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
Fix missing messages for RecevieTasks (#35)
Browse files Browse the repository at this point in the history
* Fix missing messages for RecevieTasks

* Fix linting issues
  • Loading branch information
wederbn authored Aug 2, 2021
1 parent 121025f commit 6a6a7e6
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 40 deletions.
4 changes: 2 additions & 2 deletions client/src/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ export class App extends PureComponent {
type: 'info',
title: 'QAA import pending!',
content: 'QAA import for ' + qaaPaths.length + ' QAAs is running in the background. Uploading CSARs to connected Winery!',
duration: 100000
duration: 300000
});

return await this.tabRef.current.triggerAction('import-qaa', {
Expand Down Expand Up @@ -1497,7 +1497,7 @@ export class App extends PureComponent {
type: 'info',
title: 'QAA export pending!',
content: 'QAA export is currently pending. Retrieving required CSARs from connected Winery. Please wait until the file dialog opens to store the QAA locally!',
duration: 100000
duration: 300000
});
}

Expand Down
5 changes: 5 additions & 0 deletions client/src/app/quantme/utilities/Utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ export function getPropertiesToCopy(element) {
continue;
}

// ignore messages, as they are added before
if (key === 'messageRef') {
continue;
}

properties[key] = element[key];
}

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions resources/plugins/QuantME-CamundaPlugin/quantme/Utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,21 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { getRootProcess } from 'client/src/app/quantme/utilities/Utilities';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import elementTemplates from 'bpmn-js-properties-panel/lib/provider/camunda/element-templates';
import quantMEModule from './modeling';
import quantMEModdleExtension from 'client/resources/quantme/quantum4bpmn.json';
import camundaModdlePackage from 'camunda-bpmn-moddle/resources/camunda';

/**
* Get the root process from a xml string representing a BPMN diagram
* Get the definitions from a xml string representing a BPMN diagram
*
* @param xml the xml representing the BPMN diagram
* @return the root process from the xml definitions
* @return the definitions from the xml definitions
*/
export async function getRootProcessFromXml(xml) {
export async function getDefinitionsFromXml(xml) {
let bpmnModeler = await createModelerFromXml(xml);

// extract and return root process
return getRootProcess(bpmnModeler.getDefinitions());
return bpmnModeler.getDefinitions();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { getRootProcessFromXml } from '../Utilities';
import { getSingleFlowElement, isQuantMETask } from 'client/src/app/quantme/utilities/Utilities';
import { getDefinitionsFromXml } from '../Utilities';
import { getRootProcess, getSingleFlowElement, isQuantMETask } from 'client/src/app/quantme/utilities/Utilities';
import { taskMatchesDetector } from 'client/src/app/quantme/replacement/QuantMEMatcher';

export async function matchesQRM(qrm, task) {
console.log('Matching QRM %s and task with id %s!', qrm.qrmUrl, task.id);

// check whether the detector is valid and contains exactly one QuantME task
let rootProcess = await getRootProcessFromXml(qrm.detector);
let rootProcess = getRootProcess(await getDefinitionsFromXml(qrm.detector));
let detectorElement = getSingleFlowElement(rootProcess);
if (detectorElement === undefined || !isQuantMETask(detectorElement)) {
console.log('Unable to retrieve QuantME task from detector: ', qrm.detector);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
getPropertiesToCopy,
exportXmlFromModeler
} from 'client/src/app/quantme/utilities/Utilities';
import { getRootProcessFromXml, createModelerFromXml } from '../Utilities';
import { getDefinitionsFromXml, createModelerFromXml } from '../Utilities';
import { addQuantMEInputParameters } from 'client/src/app/quantme/replacement/InputOutputHandler';
import * as Constants from 'client/src/app/quantme/Constants';
import { replaceHardwareSelectionSubprocess } from './hardware-selection/QuantMEHardwareSelectionHandler';
Expand All @@ -33,13 +33,13 @@ import { replaceHardwareSelectionSubprocess } from './hardware-selection/QuantME
*/
export async function startReplacementProcess(xml, currentQRMs, endpointConfig) {
let modeler = await createModelerFromXml(xml);
let bpmnReplace = modeler.get('bpmnReplace');
let modeling = modeler.get('modeling');
let factory = modeler.get('bpmnFactory');
let elementRegistry = modeler.get('elementRegistry');

// get root element of the current diagram
const rootElement = getRootProcess(modeler.getDefinitions());
const definitions = modeler.getDefinitions();
const rootElement = getRootProcess(definitions);
console.log(rootElement);
if (typeof rootElement === 'undefined') {
console.log('Unable to retrieve root process element from definitions!');
return { status: 'failed', cause: 'Unable to retrieve root process element from definitions!' };
Expand Down Expand Up @@ -76,11 +76,10 @@ export async function startReplacementProcess(xml, currentQRMs, endpointConfig)
let replacementSuccess = false;
if (replacementConstruct.task.$type === Constants.QUANTUM_HARDWARE_SELECTION_SUBPROCESS) {
console.log('Transforming QuantumHardwareSelectionSubprocess...');
replacementSuccess = await replaceHardwareSelectionSubprocess(replacementConstruct.task, replacementConstruct.parent, factory,
bpmnReplace, elementRegistry, modeling, endpointConfig.nisqAnalyzerEndpoint, endpointConfig.transformationFrameworkEndpoint, endpointConfig.camundaEndpoint);
replacementSuccess = await replaceHardwareSelectionSubprocess(replacementConstruct.task, replacementConstruct.parent, modeler, endpointConfig.nisqAnalyzerEndpoint, endpointConfig.transformationFrameworkEndpoint, endpointConfig.camundaEndpoint);
} else {
console.log('Replacing task with id %s by using QRM: ', replacementConstruct.task.id, replacementConstruct.qrm);
replacementSuccess = await replaceByFragment(replacementConstruct.task, replacementConstruct.parent, replacementConstruct.qrm.replacement, factory, bpmnReplace, elementRegistry, modeling);
replacementSuccess = await replaceByFragment(definitions, replacementConstruct.task, replacementConstruct.parent, replacementConstruct.qrm.replacement, modeler);
}

if (!replacementSuccess) {
Expand Down Expand Up @@ -139,23 +138,24 @@ async function getMatchingQRM(task, currentQRMs) {
/**
* Replace the given task by the content of the replacement fragment
*/
async function replaceByFragment(task, parent, replacement, bpmnFactory, bpmnReplace, elementRegistry, modeling) {
async function replaceByFragment(definitions, task, parent, replacement, modeler) {
let bpmnFactory = modeler.get('bpmnFactory');

if (!replacement) {
console.log('Replacement fragment is undefined. Aborting replacement!');
return false;
}

// get the root process of the replacement fragment
let replacementProcess = await getRootProcessFromXml(replacement);
let replacementProcess = getRootProcess(await getDefinitionsFromXml(replacement));
let replacementElement = getSingleFlowElement(replacementProcess);
if (replacementElement === null || replacementElement === undefined) {
console.log('Unable to retrieve QuantME task from replacement fragment: ', replacement);
return false;
}

console.log('Replacement element: ', replacementElement);
let result = insertShape(parent, replacementElement, {}, true, bpmnReplace, elementRegistry, modeling, task);
let result = insertShape(definitions, parent, replacementElement, {}, true, modeler, task);

// add all attributes of the replaced QuantME task to the input parameters of the replacement fragment
let inputOutputExtension = getCamundaInputOutput(result['element'].businessObject, bpmnFactory);
Expand All @@ -167,18 +167,21 @@ async function replaceByFragment(task, parent, replacement, bpmnFactory, bpmnRep
/**
* Insert the given element and all child elements into the diagram
*
* @param definitions the definitions element of the BPMN diagram
* @param parent the parent element under which the new element should be attached
* @param newElement the new element to insert
* @param idMap the idMap containing a mapping of ids defined in newElement to the new ids in the diagram
* @param replace true if the element should be inserted instead of an available element, false otherwise
* @param bpmnReplace the facility to replace BPMN elements
* @param elementRegistry the registry to retrieve elements from the diagram
* @param modeling the facility to access shapes in the diagram
* @param modeler the BPMN modeler containing the target BPMN diagram
* @param oldElement an old element that is only required if it should be replaced by the new element
* @return {{success: boolean, idMap: *, element: *}}
*/
export function insertShape(parent, newElement, idMap, replace, bpmnReplace, elementRegistry, modeling, oldElement) {
export function insertShape(definitions, parent, newElement, idMap, replace, modeler, oldElement) {
console.log('Inserting shape for element: ', newElement);
let bpmnReplace = modeler.get('bpmnReplace');
let bpmnFactory = modeler.get('bpmnFactory');
let modeling = modeler.get('modeling');
let elementRegistry = modeler.get('elementRegistry');

// create new id map if not provided
if (idMap === undefined) {
Expand Down Expand Up @@ -217,6 +220,27 @@ export function insertShape(parent, newElement, idMap, replace, bpmnReplace, ele
// expand the new element
elementRegistry.get(element.id).businessObject.di.isExpanded = true;
}

// preserve messages defined in ReceiveTasks
} else if (newElement.$type === 'bpmn:ReceiveTask') {

// get message from the replacement and check if a corresponding message was already created
let oldMessage = newElement.messageRef;
if (idMap[oldMessage.id] === undefined) {

// add a new message element to the definitions document and link it to the receive task
let message = bpmnFactory.create('bpmn:Message');
message.name = oldMessage.name;
definitions.rootElements.push(message);
modeling.updateProperties(element, { 'messageRef': message });

// store id if other receive tasks reference the same message
idMap[oldMessage.id] = message.id;
} else {

// reuse already created message and add it to receive task
modeling.updateProperties(element, { 'messageRef': idMap[oldMessage.id] });
}
}

// add element to which a boundary event is attached
Expand All @@ -230,7 +254,7 @@ export function insertShape(parent, newElement, idMap, replace, bpmnReplace, ele
modeling.updateProperties(element, getPropertiesToCopy(newElement));

// recursively handle children of the current element
let resultTuple = insertChildElements(element, newElement, idMap, bpmnReplace, elementRegistry, modeling);
let resultTuple = insertChildElements(definitions, element, newElement, idMap, modeler);

// add artifacts with their shapes to the diagram
let success = resultTuple['success'];
Expand All @@ -239,7 +263,7 @@ export function insertShape(parent, newElement, idMap, replace, bpmnReplace, ele
if (artifacts) {
console.log('Element contains %i artifacts. Adding corresponding shapes...', artifacts.length);
for (let i = 0; i < artifacts.length; i++) {
let result = insertShape(element, artifacts[i], idMap, false, bpmnReplace, elementRegistry, modeling);
let result = insertShape(definitions, element, artifacts[i], idMap, false, modeler);
success = success && result['success'];
idMap = result['idMap'];
}
Expand All @@ -252,15 +276,14 @@ export function insertShape(parent, newElement, idMap, replace, bpmnReplace, ele
/**
* Insert all children of the given element into the diagram
*
* @param definitions the definitions element of the BPMN diagram
* @param parent the element that is the new parent of the inserted elements
* @param newElement the new element to insert the children for
* @param idMap the idMap containing a mapping of ids defined in newElement to the new ids in the diagram
* @param bpmnReplace the facility to replace BPMN elements
* @param elementRegistry the registry to retrieve elements from the diagram
* @param modeling the facility to access shapes in the diagram
* @param modeler the BPMN modeler containing the target BPMN diagram
* @return {{success: boolean, idMap: *, element: *}}
*/
function insertChildElements(parent, newElement, idMap, bpmnReplace, elementRegistry, modeling) {
function insertChildElements(definitions, parent, newElement, idMap, modeler) {

let success = true;
let flowElements = newElement.flowElements;
Expand All @@ -280,21 +303,21 @@ function insertChildElements(parent, newElement, idMap, bpmnReplace, elementRegi
continue;
}

let result = insertShape(parent, flowElements[i], idMap, false, bpmnReplace, elementRegistry, modeling);
let result = insertShape(definitions, parent, flowElements[i], idMap, false, modeler);
success = success && result['success'];
idMap = result['idMap'];
}

// handle boundary events with new ids of added elements
for (let i = 0; i < boundaryEvents.length; i++) {
let result = insertShape(parent, boundaryEvents[i], idMap, false, bpmnReplace, elementRegistry, modeling);
let result = insertShape(definitions, parent, boundaryEvents[i], idMap, false, modeler);
success = success && result['success'];
idMap = result['idMap'];
}

// handle boundary events with new ids of added elements
for (let i = 0; i < sequenceflows.length; i++) {
let result = insertShape(parent, sequenceflows[i], idMap, false, bpmnReplace, elementRegistry, modeling);
let result = insertShape(definitions, parent, sequenceflows[i], idMap, false, modeler);
success = success && result['success'];
idMap = result['idMap'];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ import { createModeler, createModelerFromXml } from '../../Utilities';
/**
* Replace the given QuantumHardwareSelectionSubprocess by a native subprocess orchestrating the hardware selection
*/
export async function replaceHardwareSelectionSubprocess(subprocess, parent, bpmnFactory, bpmnReplace, elementRegistry, modeling, nisqAnalyzerEndpoint, transformationFrameworkEndpoint, camundaEndpoint) {
export async function replaceHardwareSelectionSubprocess(subprocess, parent, modeler, nisqAnalyzerEndpoint, transformationFrameworkEndpoint, camundaEndpoint) {
let bpmnReplace = modeler.get('bpmnReplace');
let bpmnFactory = modeler.get('bpmnFactory');
let modeling = modeler.get('modeling');
let elementRegistry = modeler.get('elementRegistry');

// replace QuantumHardwareSelectionSubprocess with traditional subprocess
let element = bpmnReplace.replaceElement(elementRegistry.get(subprocess.id), { type: 'bpmn:SubProcess' });
Expand Down Expand Up @@ -286,15 +290,16 @@ async function getHardwareSelectionFragment(subprocess) {
await initializeModeler();

// retrieve root element to add extracted workflow fragment
let rootElement = getRootProcess(modeler.getDefinitions());
let definitions = modeler.getDefinitions();
let rootElement = getRootProcess(definitions);
let rootElementBo = elementRegistry.get(rootElement.id);

// add start and end event to the new process
let startEvent = bpmnReplace.replaceElement(elementRegistry.get(rootElement.flowElements[0].id), { type: 'bpmn:StartEvent' });
let endEvent = modeling.createShape({ type: 'bpmn:EndEvent' }, { x: 50, y: 50 }, rootElementBo, {});

// insert given subprocess and connect to start and end event
let insertedSubprocess = insertShape(rootElementBo, subprocess, {}, false, bpmnReplace, elementRegistry, modeling).element;
let insertedSubprocess = insertShape(definitions, rootElementBo, subprocess, {}, false, modeler).element;
modeling.connect(startEvent, insertedSubprocess, { type: 'bpmn:SequenceFlow' });
modeling.connect(insertedSubprocess, endEvent, { type: 'bpmn:SequenceFlow' });

Expand Down

0 comments on commit 6a6a7e6

Please sign in to comment.