Skip to content

Commit

Permalink
Attach policies to QuantME tasks (#127)
Browse files Browse the repository at this point in the history
* attach policies to quantme

* Use inline transformation as default

* fix replace option

* remove copy paste

* Attach policies to ServiceTasks and Subprocesses during transformation

* Fix typo in subprocess check

* Retrieve relevant tasks within subprocess for policy attachment

* Copy policies for subprocesses

* add ondemand attribute to quantme tasks

* add entry for ondemand

* Fix layouting issues for policies

* Always expand subprocesses during transformation

* Only move policies if defined at tasks

* Layout policies

* update size of policy icons

* fix for layouting when transforming qrms that contain a subprocess

* add createLayoutedShape function

* linting

---------

Co-authored-by: LaviniaStiliadou <livia_16@live.de>
Co-authored-by: mbeisel <beiselmn@gmail.com>
  • Loading branch information
3 people authored Nov 24, 2023
1 parent 8ac82a1 commit f38e4ad
Show file tree
Hide file tree
Showing 15 changed files with 556 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
const defaultConfig = {
camundaEndpoint: process.env.CAMUNDA_ENDPOINT,
fileName: process.env.DOWNLOAD_FILE_NAME,
transformedWorkflowHandler: transformedWorkflowHandlers.NEW_TAB,
transformedWorkflowHandler: transformedWorkflowHandlers.INLINE,
autoSaveFileOption: autoSaveFile.INTERVAL,
fileFormat: saveFileFormats.BPMN,
autoSaveIntervalSize: process.env.AUTOSAVE_INTERVAL,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isFlowLikeElement } from "./ModellingUtilities";
import { getDi, is } from "bpmn-js/lib/util/ModelUtil";
import { createLayoutedShape } from "./camunda-utils/ElementUtil";

/**
* Insert the given element and all child elements into the diagram
Expand Down Expand Up @@ -42,11 +43,11 @@ export function insertShape(
});
} else {
// create new shape for this element
element = modeling.createShape(
element = createLayoutedShape(
modeling,
{ type: newElement.$type },
{ x: 50, y: 50 },
parent,
{}
parent
);
}
} else {
Expand All @@ -57,7 +58,6 @@ export function insertShape(
type: newElement.$type,
});
}

// store id to create sequence flows
idMap[newElement["id"]] = element.id;

Expand All @@ -69,13 +69,9 @@ export function insertShape(
"quantme:CircuitCuttingSubprocess",
].includes(newElement.$type)
) {
// get the shape element related to the subprocess
// get the shape element related to the subprocess and expand it
let shape = getDi(element);

// expand the replacement subprocess if the detector subprocess was expanded
if (shape && newElement.isExpanded === "true") {
shape.isExpanded = true;
}
shape.isExpanded = true;

// preserve messages defined in ReceiveTasks
} else if (newElement.$type === "bpmn:ReceiveTask" && newElement.messageRef) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,22 @@ export function findRootElementById(businessObject, type, id) {

return elements.find((element) => element.id === id);
}

export function createLayoutedShape(modeling, type, size, parent, parentIndex) {
let resetWidth;
let resetHeight;
if (parent.width < parent.x + size.x) {
resetWidth = parent.x;
}
if (parent.height < parent.y + size.y) {
resetHeight = parent.y;
}
let shape = modeling.createShape(type, size, parent, parentIndex);
if (resetWidth) {
parent.width = parent.width - resetWidth;
}
if (resetHeight) {
parent.height = parent.height - resetHeight;
}
return shape;
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,40 +46,38 @@ export default class OpenTOSCAReplaceMenuProvider {
// add additional elements to replace policies
if (is(element, "bpmn:Event")) {
if (element.host !== undefined) {
if (element.host.type === "bpmn:ServiceTask") {
let attachers = element.host.attachers;
let attacherTypes = [];
for (let i = 0; i < attachers.length; i++) {
let attacher = attachers[i];
let attacherType = attacher.type;
let attachers = element.host.attachers;
let attacherTypes = [];
for (let i = 0; i < attachers.length; i++) {
let attacher = attachers[i];
let attacherType = attacher.type;

// Add the attacher type to the array if it's not already there
if (
!attacherTypes.includes(attacherType) &&
attacherType !== element.type
) {
attacherTypes.push(attacherType);
}
// Add the attacher type to the array if it's not already there
if (
!attacherTypes.includes(attacherType) &&
attacherType !== element.type
) {
attacherTypes.push(attacherType);
}
}

const filteredOptions = filter(
opentoscaReplaceOptions.POLICY,
isDifferentType(element)
);
const filteredOptions = filter(
opentoscaReplaceOptions.POLICY,
isDifferentType(element)
);

const filteredOptionsBasedOnAttachers = filteredOptions.filter(
(option) => {
return !attacherTypes.includes(option.target.type);
}
);
const policyEntries = createMenuEntries(
element,
filteredOptionsBasedOnAttachers,
self.translate,
self.bpmnReplace.replaceElement
);
return Object.assign(policyEntries, entries);
}
const filteredOptionsBasedOnAttachers = filteredOptions.filter(
(option) => {
return !attacherTypes.includes(option.target.type);
}
);
const policyEntries = createMenuEntries(
element,
filteredOptionsBasedOnAttachers,
self.translate,
self.bpmnReplace.replaceElement
);
return Object.assign(policyEntries, entries);
}
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@
"type": "String"
},
{
"name": "onDemand",
"name": "connectorUrl",
"isAttr": true,
"type": "String"
},
}
]
},
{
"name": "Task",
"extends": ["bpmn:Task"],
"properties": [
{
"name": "connectorUrl",
"name": "onDemand",
"isAttr": true,
"type": "String"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,26 @@ export function deletePolicies(modeler, serviceTaskId) {
modeling.removeShape(policy);
}
}

/**
* Move all policies to the new target
*
* @param modeler the modeler to which the policies belong to
* @param newTargetId the ID of the new target element
* @param policies the set of policies to move
*/
export function movePolicies(modeler, newTargetId, policies) {
let elementRegistry = modeler.get("elementRegistry");
let modeling = modeler.get("modeling");

policies.forEach((policy) => {
let hostElement = elementRegistry.get(newTargetId);
let policyElement = elementRegistry.get(policy.id);
console.log("Parent element: ", hostElement);
console.log("Policy type: ", policyElement);
modeling.updateProperties(policyElement, {
attachedToRef: hostElement.businessObject,
});
policyElement.host = hostElement;
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,19 @@ export const QUANTME_DATA_OBJECTS = [
EVALUATION_RESULT_OBJECT,
PARAMETRIZATION_OBJECT,
];

export const QUANTME_TASKS = [
QUANTUM_COMPUTATION_TASK,
QUANTUM_CIRCUIT_LOADING_TASK,
DATA_PREPARATION_TASK,
ORACLE_EXPANSION_TASK,
QUANTUM_CIRCUIT_EXECUTION_TASK,
READOUT_ERROR_MITIGATION_TASK,
VARIATIONAL_QUANTUM_ALGORITHM_TASK,
WARM_STARTING_TASK,
PARAMETER_OPTIMIZATION_TASK,
RESULT_EVALUATION_TASK,
CIRCUIT_CUTTING_TASK,
CUTTING_RESULT_COMBINATION_TASK,
ERROR_CORRECTION_TASK,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/**
* Copyright (c) 2023 Institute of Architecture of Application Systems -
* University of Stuttgart
*
* This program and the accompanying materials are made available under the
* terms the Apache Software License 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: Apache-2.0
*/

import RuleProvider from "diagram-js/lib/features/rules/RuleProvider";
import * as consts from "../Constants";
import { getModeler } from "../../../editor/ModelerHandler";
import * as openToscaConsts from "../../opentosca/Constants";

export default class QuantMERules extends RuleProvider {
constructor(eventBus, modeling) {
super(eventBus);
this.modeling = modeling;

this.addRule("shape.create", 11000, function (context) {
var shape = context.shape,
target = context.target;

if (
shape.type.includes("Policy") &&
!consts.QUANTME_TASKS.includes(target.type)
) {
return false;
}
});

function canMove(context) {
var target = context.target;

if (target != undefined) {
if (context.shapes[0].type.includes("Policy")) {
return false;
}
}
}

this.addRule("elements.move", 4000, function (context) {
return canMove(context);
});

this.addRule("shape.replace", function (context) {
if (context.element.type.includes("Policy")) {
if (context.element.type === openToscaConsts.DEDICATED_HOSTING_POLICY) {
getModeler().get("modeling").updateProperties(context.element, {
"opentosca:dedicatedHosting": "true",
});
}
return false;
}
});
this.addRule("shape.append", function (context) {
if (context.element.type.includes("Policy")) {
return false;
}
});

this.addRule("connection.create", 2000, function (context) {
if (context.target.type.includes("Policy")) {
return false;
}
if (context.source.type.includes("Policy")) {
return false;
}
});

this.addRule("connection.reconnect", 2000, function (context) {
const source = context.source,
target = context.target;

if (source.type.includes("Policy") || target.type.includes("Policy")) {
return false;
}
});

this.addRule("shape.attach", 5000, function (context) {
let shapeToAttach = context.shape;
let target = context.target;

if (
shapeToAttach.type.includes("Policy") &&
consts.QUANTME_TASKS.includes(target.type)
) {
let specificPolicies = openToscaConsts.POLICIES;
specificPolicies = specificPolicies.filter(
(policy) => policy !== openToscaConsts.POLICY
);
specificPolicies = specificPolicies.filter(
(policy) => policy !== openToscaConsts.ON_DEMAND_POLICY
);
let attachedElementTypesWithPolicy = 0;
for (let i = 0; i < target.attachers.length; i++) {
if (
target.attachers[i].type.includes("Policy") &&
target.attachers[i].type !== openToscaConsts.ON_DEMAND_POLICY
) {
attachedElementTypesWithPolicy++;
}
if (specificPolicies.includes(target.attachers[i].type)) {
specificPolicies = specificPolicies.filter(
(policy) => policy !== target.attachers[i].type
);
}
}

for (let i = 0; i < target.attachers.length; i++) {
if (specificPolicies.includes(target.attachers[i].type)) {
specificPolicies = specificPolicies.filter(
(policy) => policy !== target.attachers[i].type
);
}
}
if (
attachedElementTypesWithPolicy ===
openToscaConsts.POLICIES.length - 2
) {
return false;
}

// If the specific policies are included, prevent attaching another policy
if (specificPolicies.length === 0) {
return false;
}
for (let i = 0; i < target.attachers.length; i++) {
let boundaryElement = target.attachers[i];

if (
boundaryElement.type === openToscaConsts.DEDICATED_HOSTING_POLICY &&
shapeToAttach.type === openToscaConsts.DEDICATED_HOSTING_POLICY
) {
return false;
}

if (
boundaryElement.type === openToscaConsts.ON_DEMAND_POLICY &&
shapeToAttach.type === openToscaConsts.ON_DEMAND_POLICY
) {
return false;
}

if (
boundaryElement.type === openToscaConsts.LOCATION_POLICY &&
shapeToAttach.type === openToscaConsts.LOCATION_POLICY
) {
return false;
}

if (
boundaryElement.type ===
openToscaConsts.CLOUD_DEPLOYMENT_MODEL_POLICY &&
shapeToAttach.type === openToscaConsts.CLOUD_DEPLOYMENT_MODEL_POLICY
) {
return false;
}
}
return true;
}
});
}
}

QuantMERules.$inject = ["eventBus", "modeling"];
Loading

0 comments on commit f38e4ad

Please sign in to comment.