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 | 1x 1x 1x 1x 41x 5x 5x 41x 41x 41x 41x 7x 7x 1x 1x 6x 6x 41x 5x 5x 41x 6x 6x 5x 1x 1x 41x 2x 2x 41x 6x 6x 41x 4x 4x 3x 3x 3x 3x 3x 3x 3x 3x 41x 1x 18x 13x 18x 18x 18x 18x 2x 2x 18x 2x 2x 18x 4x 4x 2x 18x 1x | import { SpelEvaluationException } from '../error/spel-evaluation-exception.js';
import { SpelMessage } from '../error/spel-message.js';
/**
* Parallels Spring TypeConverter / SpelTypeConverter
*
* Type coercion, handles implicit type conversion in SpEL.
*/
export class SpelTypeConverter {
/**
* Try converting value to target type
*/
public convertValue(value: unknown, targetType: new (...args: unknown[]) => unknown): unknown {
// null → null (any type)
if (value === null || value === undefined) {
return null;
}
// Already matching type
if (typeof value === 'string' && targetType === String) return value;
if (typeof value === 'number' && targetType === Number) return value;
if (typeof value === 'boolean' && targetType === Boolean) return value;
// String → Number
if (typeof value === 'string' && targetType === Number) {
const num = parseFloat(value);
if (isNaN(num)) {
throw new SpelEvaluationException(-1, SpelMessage.TYPE_CONVERSION_ERROR, value, 'Number');
}
return num;
}
// Number → String
if (typeof value === 'number' && targetType === String) {
return String(value);
}
// String → Boolean
if (typeof value === 'string' && targetType === Boolean) {
const s = value.toLowerCase();
if (s === 'true') return true;
if (s === 'false') return false;
throw new SpelEvaluationException(-1, SpelMessage.TYPE_CONVERSION_ERROR, value, 'Boolean');
}
// Boolean → String
if (typeof value === 'boolean' && targetType === String) {
return String(value);
}
// Number → Boolean (non-zero is truthy)
if (typeof value === 'number' && targetType === Boolean) {
return value !== 0;
}
// Boolean → Number
if (typeof value === 'boolean' && targetType === Number) {
return value ? 1 : 0;
}
// Cannot convert — value must be object/function at this point
const typeLabel = typeof value;
const valueStr = typeLabel;
throw new SpelEvaluationException(
-1,
SpelMessage.TYPE_CONVERSION_ERROR,
`${valueStr} (${typeLabel})`,
targetType.name,
);
}
/**
* Check if conversion is possible
*/
public canConvert(value: unknown, targetType: new (...args: unknown[]) => unknown): boolean {
if (value === null || value === undefined) return true;
const valueType = typeof value;
if (valueType === 'string' && targetType === String) return true;
if (valueType === 'number' && targetType === Number) return true;
if (valueType === 'boolean' && targetType === Boolean) return true;
if (valueType === 'string' && (targetType === Number || targetType === Boolean)) {
return true;
}
if (valueType === 'number' && (targetType === String || targetType === Boolean)) {
return true;
}
if (valueType === 'boolean' && (targetType === String || targetType === Number)) {
return true;
}
return false;
}
}
|