All files / src/web/flowable/roundTrip xmlParsers.ts

95.74% Statements 45/47
76.08% Branches 70/92
100% Functions 8/8
95.74% Lines 45/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144                              41x 22x     19x       19x       207x 207x 207x 207x   207x                   41x 41x             41x                   6x                         9x                   10x 10x 10x                   48x 48x 90x 90x 48x               164x 164x 164x 164x 164x 164x     164x   164x 25x 25x 25x 139x 25x 25x 114x 25x 25x 89x 41x 41x   48x 48x     164x                
import type { Element as XmlElement } from '@xmldom/xmldom';
import type {
	FlowableEventListener,
	FlowableEventListenerImplType,
	FlowableFieldExtension,
	FlowableFormProperty,
	FlowableIOParameter,
	FlowableListener,
	FlowableMultiInstance,
	FlowableTimerDefinition,
	TimerDefinitionType,
} from '../types';
import { buildXmlIdentity, findDirectChild, getActivitiAttribute, getElementChildren, getLocalName } from './xmlUtils';
 
function resolveListenerImplementationType(element: XmlElement): FlowableListener['implementationType'] {
	if (getActivitiAttribute(element, 'class') || element.getAttribute('class')) {
		return 'class';
	}
 
	Iif (getActivitiAttribute(element, 'expression') || element.getAttribute('expression')) {
		return 'expression';
	}
 
	return 'delegateExpression';
}
 
export function parseFieldExtension(element: XmlElement): FlowableFieldExtension {
	const name = element.getAttribute('name') || '';
	const valueElement = getElementChildren(element)[0];
	const valueType = valueElement && getLocalName(valueElement) === 'expression' ? 'expression' : 'string';
	const value = valueElement?.textContent || '';
 
	return {
		id: `${name || 'field'}-${valueType}-${value}`,
		name,
		valueType,
		value,
		xmlIdentity: buildXmlIdentity('fieldExtension', element),
	};
}
 
export function parseListener(element: XmlElement): FlowableListener {
	const implementationType = resolveListenerImplementationType(element);
	const implementation =
		getActivitiAttribute(element, implementationType) ||
		element.getAttribute('class') ||
		element.getAttribute('expression') ||
		element.getAttribute('delegateExpression') ||
		'';
 
	return {
		id: `${element.nodeName}-${element.getAttribute('event') || 'event'}-${implementation}`,
		event: (element.getAttribute('event') || 'start') as FlowableListener['event'],
		implementationType,
		implementation,
		xmlIdentity: buildXmlIdentity('listener', element),
	};
}
 
export function parseFormProperty(element: XmlElement): FlowableFormProperty {
	return {
		id: element.getAttribute('id') || '',
		name: element.getAttribute('name') || '',
		type: (element.getAttribute('type') || 'string') as FlowableFormProperty['type'],
		required: (element.getAttribute('required') || '').toLowerCase() === 'true',
		readable: (element.getAttribute('readable') || 'true').toLowerCase() !== 'false',
		writable: (element.getAttribute('writable') || 'true').toLowerCase() !== 'false',
		defaultValue: element.getAttribute('default') || '',
		xmlIdentity: buildXmlIdentity('formProperty', element),
	};
}
 
export function parseIOParameter(element: XmlElement): FlowableIOParameter {
	return {
		id: `io-${element.getAttribute('source') || element.getAttribute('sourceExpression') || ''}-${element.getAttribute('target') || ''}`,
		source: element.getAttribute('source') || '',
		sourceExpression: element.getAttribute('sourceExpression') || '',
		target: element.getAttribute('target') || '',
		xmlIdentity: buildXmlIdentity('ioParameter', element),
	};
}
 
export function parseMultiInstance(element: XmlElement): FlowableMultiInstance {
	const loopCardinality = findDirectChild(element, 'loopCardinality');
	const completionCondition = findDirectChild(element, 'completionCondition');
	return {
		sequential: element.getAttribute('isSequential') === 'true',
		loopCardinality: loopCardinality?.textContent || '',
		collection: getActivitiAttribute(element, 'collection') || element.getAttribute('collection') || '',
		elementVariable: getActivitiAttribute(element, 'elementVariable') || element.getAttribute('elementVariable') || '',
		completionCondition: completionCondition?.textContent || '',
	};
}
 
export function parseTimerDefinition(element: XmlElement): FlowableTimerDefinition | null {
	const timerTypes: TimerDefinitionType[] = ['timeDuration', 'timeDate', 'timeCycle'];
	for (const type of timerTypes) {
		const child = findDirectChild(element, type);
		if (child) {
			return { type, value: child.textContent || '' };
		}
	}
 
	return { type: 'timeDuration', value: '' };
}
 
export function parseEventListener(element: XmlElement): FlowableEventListener {
	const events = element.getAttribute('events') || '';
	const className = element.getAttribute('class') || getActivitiAttribute(element, 'class') || '';
	const delegateExpr = element.getAttribute('delegateExpression') || getActivitiAttribute(element, 'delegateExpression') || '';
	const throwSignal = element.getAttribute('signalName') || '';
	const throwMessage = element.getAttribute('messageName') || '';
	const throwError = element.getAttribute('errorCode') || '';
 
	let implementationType: FlowableEventListenerImplType;
	let implementation = '';
 
	if (throwSignal) {
		const isGlobal = element.getAttribute('throwGlobalEvent') === 'true';
		implementationType = isGlobal ? 'throwGlobalSignalEvent' : 'throwSignalEvent';
		implementation = throwSignal;
	} else if (throwMessage) {
		implementationType = 'throwMessageEvent';
		implementation = throwMessage;
	} else if (throwError) {
		implementationType = 'throwErrorEvent';
		implementation = throwError;
	} else if (delegateExpr) {
		implementationType = 'delegateExpression';
		implementation = delegateExpr;
	} else {
		implementationType = 'class';
		implementation = className;
	}
 
	return {
		id: `eventListener-${events}-${implementation}`,
		events,
		implementationType,
		implementation,
		entityType: element.getAttribute('entityType') || '',
		xmlIdentity: buildXmlIdentity('processEventListener', element),
	};
}