Skip to content

Conversation

@akantchev
Copy link
Contributor

@akantchev akantchev commented Oct 21, 2025

Implementation of Switch Canvas Item

Description

Add implementation of switch canvas item supported in vRO so that it will be generated whenever there is a corresponding annotations in the typescript implementation of a vRO workflow is found.

Checklist

  • I have added relevant error handling and logging messages to help troubleshooting
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the PR title with affected component, related issue number and a short summary of the changes introduced
  • I have added labels for implementation kind (kind/) and version type (version/)
  • I have my changes rebased and squashed to the minimal number of relevant commits. Notice: don't squash all commits
  • I have added a descriptive commit message with a short title, including a Fixed #XXX - or Closed #XXX - prefix to auto-close the issue

Example Workflow

import { Workflow, SwitchItem } from "vrotsc-annotations";

@Workflow({
	name: "switch all",
	path: "VMware/PSCoE",
	description: "Comprehensive switch test with all comparator types",
	attributes: {
		var_str: {
			type: "string"
		},
		var_num: {
			type: "number"
		},
		var_bool: {
			type: "boolean"
		},
	}
})
export class SwitchAll {

	@SwitchItem({
		cases: [
			// String comparisons
			{ condition: "", target: "handleEmpty", variable: "var_str", type: "string", comparator: "equals" },
			{ condition: "test", target: "handleStringOp", variable: "var_str", type: "string", comparator: "contains" },
			{ condition: "pattern", target: "handleStringOp", variable: "var_str", type: "string", comparator: "match" },
			{ condition: "value", target: "handleStringOp", variable: "var_str", type: "string", comparator: "different" },
			
			// Number comparisons
			{ condition: 1, target: "handleNumeric", variable: "var_num", type: "number", comparator: "different" },
			{ condition: 5, target: "handleNumeric", variable: "var_num", type: "number", comparator: "greater" },
			{ condition: 10, target: "handleNumeric", variable: "var_num", type: "number", comparator: "smaller" },
			{ condition: 0, target: "handleNumeric", variable: "var_num", type: "number", comparator: "greater or equals" },
			{ condition: 100, target: "handleNumeric", variable: "var_num", type: "number", comparator: "smaller or equals" },
			
			// Boolean comparisons
			{ condition: true, target: "handleBoolean", variable: "var_bool", type: "boolean", comparator: "equals" },
			{ condition: false, target: "handleBoolean", variable: "var_bool", type: "boolean", comparator: "different" }
		],
		target: "handleDefault"
	})
	public switchElement() {
		// Switch logic will be generated automatically
	}

	public handleEmpty() {
		System.log("Handling empty string");
	}

	public handleStringOp() {
		System.log("Handling string operation");
	}

	public handleNumeric() {
		System.log("Handling numeric operation");
	}

	public handleBoolean() {
		System.log("Handling boolean operation");
	}

	public handleDefault() {
		System.log("Handling default case");
	}
}

Testing

End to end tests were included

Release Notes

Add support for switch schema element in vRO workflow that is similar to @DecisionItem.

Related issues and PRs

Related issue:

#869

@akantchev akantchev requested a review from a team as a code owner October 21, 2025 11:12
@github-actions github-actions bot added the kind/feature New Feature to the project label Oct 21, 2025
@VenelinBakalov VenelinBakalov self-assigned this Oct 21, 2025
@VenelinBakalov
Copy link
Collaborator

VenelinBakalov commented Oct 22, 2025

@akantchev thanks a ton for helping out! I still haven't had time to fully review, I will try to check it later this week and hopefully test it.
Just a quick question - I saw in the readme that we support equals comparator. Would it be possible to support also the other values since in Orchestrator I see we support 7 comparators?
image
I can also try to help out and extend it. I was even thinking if we can do a mapping of string values to number (e.g. "equals" input to be converted to 0 which was the actual value in the XML)

@VenelinBakalov
Copy link
Collaborator

Btw if we decide to use string values for comparator we need to export those values as a type. I've tried using enum for a previous extension (resume and restart behaviour - https://github.com/vmware/build-tools-for-vmware-aria/pull/851/files) and the enum is not properly resolved.
So an alternative to use something like:
export type switchComparator = "equals" | "different" .... | "is defined";

this way we are free to use human readable strings but at the same time we will still have a form of autocompletion:
image

And then we can map these strings to number with a simple switch that can even be wrapped in a private function for extracting the value

…ted wrongly removed exception optional parameter for the user interaction component

Signed-off-by: akantchev
@akantchev
Copy link
Contributor Author

Hi @VenelinBakalov I've updated the PR so it supports now all comparators that are supported by vRO.

@VenelinBakalov
Copy link
Collaborator

Sorry for the delay, I will try to reprioritise this soon.
I see some minor difference in the supported types, when I get back to reviewing I will create a test workflow and export all the possible cases so we can have an exact mapping with the expected numbers.

@VenelinBakalov
Copy link
Collaborator

I made a fairly detailed check at least for the basic types of string, num and bool and it seems we have quite a few values. the good thing is that at the end they map to the same numeric values for the comparison. the bad thing is that the autogenerated code differs a bit...I will leave a screenshot of the test workflow and the full exported XML here:

<?xml version='1.0' encoding='UTF-8'?>
<workflow xmlns="http://vmware.com/vco/workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://vmware.com/vco/workflow http://vmware.com/vco/workflow/Workflow-v4.xsd" root-name="item1" object-name="workflow:name=generic" id="f3c974e1-f2b4-40fc-a95c-c7d21b2606e3" version="0.0.0" api-version="6.0.0" allowed-operations="vfe" editor-version="2.0" restartMode="1" resumeFromFailedMode="0">
  <display-name><![CDATA[switch all]]></display-name>
  <position y="50.0" x="100.0"/>
  <attrib name="var_str" type="string" read-only="false">
    <value encoded="n"><![CDATA[]]></value>
  </attrib>
  <attrib name="var_num" type="number" read-only="false">
    <value encoded="n"><![CDATA[]]></value>
  </attrib>
  <attrib name="var_bool" type="boolean" read-only="false">
    <value encoded="n"><![CDATA[false]]></value>
  </attrib>
  <workflow-item name="item0" type="end" end-mode="0">
    <in-binding/>
    <position y="40.0" x="480.0"/>
  </workflow-item>
  <workflow-item name="item1" out-name="item2" type="task">
    <display-name><![CDATA[Scriptable task]]></display-name>
    <in-binding/>
    <out-binding/>
    <description><![CDATA[Simple task with custom script capability.]]></description>
    <position y="60.0" x="170.0"/>
  </workflow-item>
  <workflow-item name="item2" type="switch">
    <display-name><![CDATA[Switch]]></display-name>
    <script encoded="false"><![CDATA[// Generated by the system, cannot be edited
if (var_str === "") {
  return "item0";
} else if (var_str.indexOf("") !== -1) {
  return "item1";
} else if (var_str.match("null") !== null) {
  return "item1";
} else if (var_str !== null) {
  return "item1";
} else if (var_num !== 1) {
  return "item1";
} else if (var_num > ) {
  return "item1";
} else if (var_num < ) {
  return "item1";
} else if (var_num !== null) {
  return "item1";
} else if (var_num >= ) {
  return "item1";
} else if (var_num <= ) {
  return "item1";
} else if (var_bool === true) {
  return "item1";
} else if (var_bool === false) {
  return "item1";
} else if (true) {
  return "item0";
}
]]></script>
    <in-binding>
      <bind name="var_str" type="string" export-name="var_str"/>
      <bind name="var_num" type="number" export-name="var_num"/>
      <bind name="var_bool" type="boolean" export-name="var_bool"/>
    </in-binding>
    <out-binding/>
    <condition name="var_str" type="string" comparator="0" label="item0"/>
    <condition name="var_str" type="string" comparator="1" label="item1"/>
    <condition name="var_str" type="string" comparator="2" label="item1"/>
    <condition name="var_str" type="string" comparator="3" label="item1"/>
    <condition name="var_num" type="number" comparator="1" label="item1">1</condition>
    <condition name="var_num" type="number" comparator="2" label="item1"/>
    <condition name="var_num" type="number" comparator="3" label="item1"/>
    <condition name="var_num" type="number" comparator="4" label="item1"/>
    <condition name="var_num" type="number" comparator="5" label="item1"/>
    <condition name="var_num" type="number" comparator="6" label="item1"/>
    <condition name="var_bool" type="boolean" comparator="0" label="item1"/>
    <condition name="var_bool" type="boolean" comparator="1" label="item1"/>
    <condition name="" type="boolean" comparator="6" label="item0"/>
    <description><![CDATA[Basic switch activity based on a workflow attribute or parameter.]]></description>
    <position y="50.0" x="260.0"/>
  </workflow-item>
  <presentation/>
</workflow>
Screenshot 2025-10-30 at 10 38 46

Based on the above I am not sure whether it will be easier to switch to string comparators, e.g. "equals" instead of "===" so that it is not confusing.

E.g. based on what I see above string -> contains comparator maps to 1. At the same time number -> different maps to 1 as well

@VenelinBakalov VenelinBakalov added lang/typescript Related to typescript code area/vrotsc Relates to `vrotsc` module version/minor Introduces a non-breaking feature or change labels Oct 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/vrotsc Relates to `vrotsc` module kind/feature New Feature to the project lang/typescript Related to typescript code version/minor Introduces a non-breaking feature or change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants