import ExpressionType from '../enums/ExpressionType' import BreakWayException from '../exception/BreakWayException' import ContinueWayException from '../exception/ContinueWayException' import ExpressionException from '../exception/ExpressionException' import ReturnWayException from '../exception/ReturnWayException' import ServiceException from '../exception/ServiceException' import JSONArray from '../instances/JSONArray' import JSONObject from '../instances/JSONObject' import Delegate from './Delegate' export default class Expression { /** * 节点类型 */ type: ExpressionType /** * 节点值 */ value: any /** * 节点对应位置 */ pos: number /** * 子节点 */ children: (Expression | null)[] /** * 运行时对应的Delegate,Delegate中保存有实参 */ delegate?: Delegate constructor(type: ExpressionType, pos: number, value?: any, children?: Expression[], expression?: Expression) { this.type = type this.value = value this.pos = pos if (children) { this.children = children } else if (expression) { this.children = [expression] } else { this.children = [] } } /** * 产生常数 */ public static Constant(value: any, pos: number): Expression { return new Expression(ExpressionType.Constant, pos, value) } /** * 产生Lambda */ public static Lambda(lambdaExp: Expression, pos: number): Expression { return new Expression(ExpressionType.Lambda, pos, lambdaExp) } /** * 产生Return */ public static Return(objExp: Expression, pos: number): Expression { return new Expression(ExpressionType.Return, pos, null, undefined, objExp) } /** * 产生Break */ public static Break(pos: number, objExp?: Expression): Expression { return new Expression(ExpressionType.Break, pos, null, undefined, objExp) } /** * 产生Continue */ public static Continue(pos: number, objExp?: Expression): Expression { return new Expression(ExpressionType.Continue, pos, null, undefined, objExp) } /** * 产生Throw */ public static Throw(objExp: Expression, pos: number): Expression { return new Expression(ExpressionType.Throw, pos, null, undefined, objExp) } /** * 产生Assert */ public static Assert(objExp: Expression, pos: number): Expression { return new Expression(ExpressionType.Assert, pos, null, undefined, objExp) } /** * 产生Validate */ public static Validate(objExp: Expression, pos: number): Expression { return new Expression(ExpressionType.Validate, pos, null, undefined, objExp) } /** * 产生标识符 */ public static Identity(value: any, pos: number): Expression { return new Expression(ExpressionType.Identity, pos, value) } /** * 产生Json对象,value=null, children=属性值对 */ public static Json(attrs: Expression[], pos: number): Expression { const result = new Expression(ExpressionType.Json, pos) result.children.push(...attrs) return result } /** * 逗号表达式, value=null, children=各表达式 */ public static Comma(children: Expression[], pos: number): Expression { const result = new Expression(ExpressionType.Comma, pos) result.children.push(...children) return result } /** * 函数调用 */ public static Call(objExp: Expression, name: string, params: Expression[], pos: number): Expression { const result = new Expression(ExpressionType.Call, pos, name) result.children.push(objExp) // 把所有参数加入函数调用子中 result.children.push(...params) return result } /** * 产生JSON数组 */ public static Array(params: Expression[], pos: number): Expression { return new Expression(ExpressionType.Array, pos, null, params) } /** * 产生参数 */ public static Param(objExp: Expression, value: string, pos: number): Expression { const result = new Expression(ExpressionType.Param, pos, value) result.children.push(objExp) return result } /** * 产生对象属性 */ public static Property(objExp: Expression, name: string, pos: number): Expression { const result = new Expression(ExpressionType.Property, pos, name) result.children.push(objExp) return result } /** * 产生属性表达式,value=属性名,children[0]=属性值 */ public static Attr(name: string, value: Expression, pos: number): Expression { const result = new Expression(ExpressionType.Attr, pos, name) result.children.push(value) return result } /** * 产生赋值语句,value=属性名/变量名,child[0]=赋值对象,child[1]=赋值内容 */ public static Assign(objExp: Expression | null, exp: Expression, name: string, pos: number): Expression { const result = new Expression(ExpressionType.Assign, pos, name) result.children.push(objExp) result.children.push(exp) return result } /** * 产生异常 */ public static Try(tryExp: Expression, catches: Expression[], pos: number, finallyExp?: Expression): Expression { const tryFinally: Expression[] = [] tryFinally.push(tryExp) if (finallyExp) { tryFinally.push(finallyExp) } const result = new Expression(ExpressionType.Try, pos, tryFinally) result.children.push(...catches) return result } /** * 产生Catch */ public static Catch(className: string, varName: string, catches: Expression, pos: number): Expression { const catchParameter: string[] = [] catchParameter.push(className) catchParameter.push(varName) const result = new Expression(ExpressionType.Catch, pos, catchParameter) result.children.push(catches) return result } /** * 产生一个条件语句, test:条件,ifTrue:为真时结果,ifFalse:为假时结果 */ public static Condition(test: Expression, ifTrue: Expression, ifFalse: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Condition, pos, source) result.children.push(test) result.children.push(ifTrue) result.children.push(ifFalse) return result } /** * 产生逻辑非语句 */ public static Not(exp: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Not, pos, source) result.children.push(exp) return result } /** * 产生逻辑与语句 */ public static And(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.And, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生逻辑或语句 */ public static Or(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Or, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生>比较运算 */ public static GreaterThan(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.GreaterThan, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生>=比较运算 */ public static GreaterThanOrEqual(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.GreaterThanOrEqual, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生<比较运算 */ public static LessThan(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.LessThan, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生<=比较运算 */ public static LessThanOrEqual(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.LessThanOrEqual, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生==比较运算 */ public static Equal(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Equal, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生!=比较运算 */ public static NotEqual(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.NotEqual, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生+运算 */ public static Add(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Add, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生-运算 */ public static Subtract(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Subtract, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生*运算 */ public static Multiply(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Multiply, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生/运算 */ public static Divide(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Divide, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生%运算 */ public static Modulo(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Modulo, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生字符串连接运算 */ public static Concat(left: Expression, right: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.Concat, pos, source) result.children.push(left) result.children.push(right) return result } /** * 产生数组下标 */ public static ArrayIndex(objExp: Expression, indexExp: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.ArrayIndex, pos, source) result.children.push(objExp) result.children.push(indexExp) return result } /** * 产生for循环 */ public static For(objExp: Expression, forExp: Expression, source: string, pos: number): Expression { const result = new Expression(ExpressionType.For, pos, source) result.children.push(objExp) result.children.push(forExp) return result } private static isNumberC(str: string): boolean { return !Number.isNaN(Number(str)) } /** * 覆盖toString方法,显示树状的节点信息,方便调试 */ public toString(level?: number): string { if (!level) { return this.toString(0) } else { // 显示自己的类型及名称 let result = `${this.space(level)}type: ${this.type}, value: ${ this.value ? this.value.toString() : 'null'}[\n]` // 递归显示子 for (let i = 0; i < this.children.length; i++) { const child = this.children[i] result += (child ? child.toString(level + 1) : `${this.space(level + 1)}null\n`) } result += `${this.space(level)}]\n` return result } } /** * 执行条件处理 */ private condition(): any { // 条件 const condExp = this.children[0] // 为真时表达式 const isTrue = this.children[1] // 为假时表达式 const isFalse = this.children[2] // 如果条件返回的不是bool值,则非空值为真,空值为假 const obj = condExp?.invoke() const cond = this.getBoolean(obj) // 为真,返回为真的表达式,否则,返回为假的表达式 return cond ? isTrue?.invoke() : isFalse?.invoke() } /** * 执行for循环 */ private loop(): any { const objExp = this.children[0] // 获取对象,for循环 const obj = objExp?.invoke() if (obj instanceof JSONArray || Array.isArray(obj)) { // 获取循环体,循环体中row代表每一项对象, 把对象传递给循环体执行 const body = this.children[1] if (obj instanceof JSONArray) { const array = obj as JSONArray for (let i = 0; i < array.length(); i++) { this.delegate?.put('rowIndex', i) this.delegate?.put('row', array.get(i)) try { body?.invoke() } catch (e) { if (e instanceof BreakWayException) { break } else if (e instanceof ContinueWayException) { // ignore } else { throw e } } } } else { const array = obj as Array for (let i = 0; i < array.length; i++) { this.delegate?.put('rowIndex', i) this.delegate?.put('row', array[i]) try { body?.invoke() } catch (e) { if (e instanceof BreakWayException) { break } else if (e instanceof ContinueWayException) { // ignore } else { throw e } } } } } else if (obj instanceof JSONObject || obj instanceof Object) { // 获取循环体,循环体中row代表每一项对象, 把对象传递给循环体执行 const body = this.children[1] if (obj instanceof JSONObject) { const json: JSONObject = obj as JSONObject for (const key of json.keySet()) { this.delegate?.put('rowKey', key) this.delegate?.put('row', json.get(key)) try { body?.invoke() } catch (e) { if (e instanceof BreakWayException) { break } } } } else { for (const key of obj) { this.delegate?.put('rowKey', key) this.delegate?.put('row', obj[key]) try { body?.invoke() } catch (e) { if (e instanceof BreakWayException) { break } else if (e instanceof ContinueWayException) { // ignore } else { throw e } } } } } else { let start = 0 let length: number try { if (objExp?.children.length === 2) { start = objExp?.children[0]?.invoke() length = objExp?.children[1]?.invoke() } else if (typeof obj === 'number') { length = obj as number } else { throw new ServiceException('for循环只接收集合对象,整数或两个整数的组合') } } catch (e) { throw new ServiceException('for循环只接收集合对象,整数或两个整数的组合') } // 获取循环体,循环体中row代表索引 for (let i = start; i < length; i++) { const body = this.children[1] this.delegate?.put('row', i) try { body?.invoke() } catch (e) { if (e instanceof BreakWayException) { break } else if (e instanceof ContinueWayException) { // ignore } else { throw e } } } } return obj } /** * 执行集合的where过滤 */ private where(): any { const result = new JSONArray() const objExp = this.children[0] // 获取对象,where循环只针对JSONArray及list let array: JSONArray const ret = objExp?.invoke() if (ret instanceof JSONArray) { array = ret } else if (Array.isArray(ret)) { array = new JSONArray() for (let i = 0; i < ret.length; i++) { array.put(ret[i]) } } else { throw new ServiceException('where循环只针对JSONArray, Array') } // 获取过滤内容,其中row代表每一项对象, 把对象传递进去执行 const body = this.children[1] for (let i = 0; i < array.length(); i++) { const value = array.get(i) this.delegate?.put('row', value) const value2 = body?.invoke() if (value2 === true) { result.put(value) } } return result } /** * 执行集合的sum求和,求和结果为BigDecimal */ private sum(): any { let result = 0 const objExp = this.children[0] // 获取对象,sum循环只针对JSONArray const array = objExp?.invoke() as JSONArray // 获取过滤内容,其中row代表每一项对象, 把对象传递进去执行 const body = this.children[1] for (let i = 0; i < array.length(); i++) { const value = array.get(i) this.delegate?.put('row', value) const decimal = body?.invoke().toString() if (decimal) { result = result + Number(decimal) } } return result } /** * 对函数或者取属性结果进行数值转换 */ private convert(source: any): any { if (typeof source === 'number') { return source as number } else { return source } } /** * 返回Json对象的结果,返回一个Json对象 */ private json(): any { const result: JSONObject = new JSONObject() for (const child of this.children) { const name = child?.value.toString() const value = child?.children[0]?.invoke() result.put(name, value) } return result } /** * 返回JSONArray结果 */ private array(): any { const result: JSONArray = new JSONArray() for (const child of this.children) { // 调用处理结果 const value = child?.invoke() result.put(value) } return result } /** * 根据值返回boolean结果 */ private getBoolean(obj: any): boolean { // 如果条件返回的不是bool值,则非空值为真,空值为假 let cond: boolean if (typeof obj === 'boolean') { cond = obj as boolean } else { cond = (obj != null) } return cond } /** * 执行赋值过程 */ private assign(): any { // 属性值 const right = this.children[1] const value = right?.invoke() // 获取属性 const name = this.value if (this.delegate?.getLambdaOutProps().includes(name)) { throw new ServiceException(`lambda 表达式中使用的外层参数[${name}]为常量,不允许显性改变`) } // 要赋值的对象,空代表给变量赋值 const left = this.children[0] if (left == null) { this.delegate?.put(name, value) } else { const obj = left.invoke() // 如果是JSONObject,调用JSONObject的赋值过程 if (obj instanceof JSONObject) { const json: JSONObject = obj as JSONObject json.put(name, value) } else { try { obj[name] = value return value } catch (e) { throw new ServiceException(`属性赋值错误:${name}`) } } } return value } /** * 获取对象属性 */ private property(key: string = this.value.toString()): any { const objExp = this.children[0] // 获取对象 const obj = objExp?.invoke() // 属性名 let rObj: any // 是JSONObject if (obj instanceof JSONObject) { const json = obj as JSONObject if (!json.has(key)) { return null } rObj = json.get(key) } else { rObj = obj[key] } return this.convert(rObj) } /** * 获取数组元素 */ private arrayIndex(): any { const objExp = this.children[0] const indexExp = this.children[1] // 获取对象 const obj = objExp?.invoke() // 如果对象为JSONArray,调用JSONArray的方法 if (obj instanceof JSONArray) { const array: JSONArray = obj as JSONArray // 获取下标值 const index = Number(indexExp?.invoke()) const oRet = array.get(index) return this.convert(oRet) } else if (Array.isArray(obj)) { const list = obj as Array // 获取下标值 const index = Number(indexExp?.invoke()) const oRet = list[index] return this.convert(oRet) } else { try { // 获取键 const key = indexExp?.invoke().toString() return this.property(key) } catch (e) { if (!(e instanceof Error)) { // eslint-disable-next-line no-ex-assign e = new Error(e as any) } throw new ExpressionException(this.delegate?.getSource() as string, this.pos as number, e as Error) } } } /** * 产生多个空格 */ private space(n: number): string { let result = '' for (let i = 0; i < n; i++) { result += ' ' } return result } /** * 跳出业务 */ private returnBusiness(): any { const value = this.children[0]?.invoke() throw new ReturnWayException(value) } /** * 抛出业务异常 */ private throwException(): any { let result = this.children[0]?.invoke() if (result instanceof JSONObject) { const obj: JSONObject = result as JSONObject throw new ServiceException(obj.get('msg').toString(), obj.getInt('status')) } else if (result instanceof Error) { const e = result as Error if (e instanceof ServiceException) { throw e } throw new ExpressionException(this.delegate?.getSource() as string, this.pos as number, e) } else { if (result === undefined || result === '') { result = '未定义异常' } throw new ServiceException(result.toString(), 400) } } /** * 断言处理 */ private assertExp(): any { const expression = this.children[0] const result = expression?.invoke() if (typeof result === 'boolean') { const yn = result as boolean if (!yn) { throw new ServiceException('断言校验失败', 400) } } else { throw new ServiceException('assert仅接收boolean结果') } return true } /** * 参数校验 */ private validateParams(): any { const result = this.children[0]?.invoke() if (result instanceof JSONObject) { const validateJson: JSONObject = result as JSONObject const params = this.delegate?.get('data') this.validateMain('data', params, validateJson) } else { throw new ServiceException('validate仅接收json格式的对象') } return result } /** * lambda */ private lambda(): Delegate { return new Delegate(this.value as Expression, this.delegate?.getSource() as string, this.delegate?.getObjectNames()) } /** * 参数校验实现 */ private validateMain(validateItemKey: string, params: JSONObject, validateJson: JSONObject): void { for (const key of validateJson.keySet()) { const item: JSONObject = validateJson.getJSONObject(key) const validateMode = item.optString('mode', 'normal') switch (validateMode) { case 'normal': { const hasParams: boolean = params.has(key) && params.opt(key) if (!hasParams) { if (item.optBoolean('required', false)) { const message = item.optString('message', `参数校验失败,${validateItemKey}>>${key}不能为空`) throw new ServiceException(message, 400) } if (item.has('default')) { params.put(key, item.get('default')) } } // items用于对JSON参数的成员进行校验 if (item.has('items')) { const itemsValidate = item.getJSONObject('items') this.validateMain(`${validateItemKey}>>${key}`, params.getJSONObject(key), itemsValidate) } break } case 'atLeastOne': { const fields: JSONArray = item.getJSONArray('fields') let isValidate = false for (let i = 0; i < fields.length(); i++) { const field = fields.get(i) const fieldName = field.toString() const hasParam = params.has(fieldName) && params.get(fieldName) != null if (hasParam) { isValidate = true break } } if (!isValidate) { const message = item.optString('message', `参数校验失败:参数组${fields}至少有一个不能为空`) throw new ServiceException(message, 400) } break } } } } private Param(): any { return this.children[0]?.invoke() } /** * 执行 Try-Catch-Finally 语句块 */ private try(): any { const exps: Expression[] = this.value as Expression[] const tryExp: Expression = exps[0] try { // 执行 try 块 return tryExp.invoke() } catch (ex) { const e: any = ex instanceof Error ? (ex as { cause?: any }).cause : ex // 执行 catch 块 for (const exp of this.children) { const catchValues: string[] = exp?.value as string[] const typeName: string = catchValues[0] const varName: string = catchValues[1] // 找到了 catch 部分,获取异常类型 if (this.isEqual(e, typeName)) { const catchExp = exp?.children as Expression[] // 把异常值变成变量 this.delegate?.put(varName, e) return catchExp[0].invoke() } } // 未匹配到异常,重新抛出原异常 throw ex } finally { // 执行 finally 块 if (exps.length > 1) { const finallyExp: Expression = exps[1] if (finallyExp != null) { finallyExp.invoke() } } } } /** * 判断异常类型是否匹配 */ private isEqual(exception: any, typeName: string): boolean { if (typeName === 'Exception' || typeName === 'Error') { return true } return exception && exception.constructor.name === typeName } /** * 执行 */ public invoke(): any { try { switch (this.type) { // 逻辑运算 case ExpressionType.Or: { const left: Expression = this.children[0] as Expression const l = this.getBoolean(left.invoke()) if (l === true) { return true } else { const right: Expression = this.children[1] as Expression return this.getBoolean(right.invoke()) } } case ExpressionType.And: { const left: Expression = this.children[0] as Expression const right: Expression = this.children[1] as Expression const l = this.getBoolean(left.invoke()) if (l === true) { return this.getBoolean(right.invoke()) } else { return false } } case ExpressionType.Not: { const left: Expression = this.children[0] as Expression return !this.getBoolean(left.invoke()) } // 算数运算 case ExpressionType.Add: case ExpressionType.Subtract: case ExpressionType.Multiply: case ExpressionType.Divide: case ExpressionType.Modulo: { return this.math() } // 字符串连接 case ExpressionType.Concat: { const left: Expression = this.children[0] as Expression const right: Expression = this.children[1] as Expression let l = left.invoke() if (l == null) { l = 'null' } let r = right.invoke() if (r == null) { r = 'null' } return l.toString() + r.toString() } // 返回JSON case ExpressionType.Json: { return this.json() } // 返回JSONArray case ExpressionType.Array: { return this.array() } // 比较运算 case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: { const left: Expression = this.children[0] as Expression const right: Expression = this.children[1] as Expression const l = left.invoke() const r = right.invoke() if (l == null || r == null) { return false } // 两个字符串比较 if (typeof l === 'string' && typeof r === 'string') { const result = l.localeCompare(r) // 使用localeCompare来比较字符串 return this.compare(result) } else { const dl = Number(l) // 转换成数字 const dr = Number(r) // 转换成数字 if (Number.isNaN(dl) || Number.isNaN(dr)) { return false // 如果转换失败,返回 false } return this.compare(dl - dr) // 进行数字比较 } } // 比较运算 case ExpressionType.Equal: case ExpressionType.NotEqual: { const left: Expression = this.children[0] as Expression const right: Expression = this.children[1] as Expression let l: any = left.invoke() let r: any = right.invoke() // 如果 l 或 r 为 null,替换成字符串 "null" if (l == null) { l = 'null' } if (r == null) { r = 'null' } let equals: boolean // 校验参考的是 JS 的 ==,即宽松相等比较 if ((typeof l === 'number' && typeof r === 'number') || ((typeof l === 'number' || typeof r === 'number') && this.isNumberC(l.toString()) && this.isNumberC(r.toString()))) { // 比较两个数字,使用 Number 进行转换 equals = Number(l) === Number(r) } else { // 比较字符串 equals = String(l) === String(r) } return this.type === ExpressionType.Equal ? equals : !equals } // 常数 case ExpressionType.Constant: { return this.value } // 标识符,获取实参对象 case ExpressionType.Identity: { // 如果参数不存在,返回空 const name = this.value as string if (!this.delegate?.containsKey(name)) { return null } return this.delegate?.get(name) } // 条件语句 case ExpressionType.Condition: { return this.condition() } // 获取属性值 case ExpressionType.Property: { return this.property() } // 获取数组元素 case ExpressionType.ArrayIndex: { return this.arrayIndex() } // 函数调用 case ExpressionType.Call: { return this.call() } // For循环 case ExpressionType.For: { return this.loop() } // 属性赋值 case ExpressionType.Assign: { return this.assign() } // 逗号表达式 case ExpressionType.Comma: { let value: any = 0 for (const child of this.children) { value = child?.invoke() } return value } // 异常处理 case ExpressionType.Try: { return this.try() } // 参数 case ExpressionType.Param: { return this.Param() } // Return case ExpressionType.Return: { return this.returnBusiness() } // Throw case ExpressionType.Throw: { return this.throwException() } // Assert case ExpressionType.Assert: { return this.assertExp() } // Validate case ExpressionType.Validate: { return this.validateParams() } // Lambda case ExpressionType.Lambda: { return this.lambda() } // Break case ExpressionType.Break: { throw new BreakWayException() } // Continue case ExpressionType.Continue: { throw new ContinueWayException() } default: { throw new ServiceException('无效操作') } } } catch (ex) { if (ex instanceof ReturnWayException || ex instanceof BreakWayException || ex instanceof ContinueWayException || ex instanceof ExpressionException) { throw ex } else { if (!(ex instanceof Error)) { // eslint-disable-next-line no-ex-assign ex = new Error(ex as any) } throw new ExpressionException(this.delegate?.getSource() as string, this.pos as number, ex as Error) } } } private compare(result: number): boolean { switch (this.type) { case ExpressionType.GreaterThan: return result > 0 case ExpressionType.GreaterThanOrEqual: return result >= 0 case ExpressionType.LessThan: return result < 0 case ExpressionType.LessThanOrEqual: return result <= 0 default: throw new ServiceException('未知类型') } } /** * 执行数学运算 * * @return 运算结果 */ private math(): any { const left: Expression = this.children[0] as Expression const right: Expression = this.children[1] as Expression const oLeft: any = left.invoke() const oRight: any = right.invoke() // 统一将输入转换为浮点数,既支持整数也支持浮点数 const l = Number(oLeft) // 使用 Number 统一转换 const r = Number(oRight) // 使用 Number 统一转换 if (Number.isNaN(l) || Number.isNaN(r)) { throw new ServiceException('无效的数字') } switch (this.type) { case ExpressionType.Add: return l + r case ExpressionType.Subtract: return l - r case ExpressionType.Multiply: return l * r case ExpressionType.Divide: return r !== 0 ? l / r : Number.NaN // 防止除以0 case ExpressionType.Modulo: return l % r default: throw new ServiceException('不识别的算数操作符') } } /** * 执行函数调用 */ private call(): any { // 函数名 const name: string = this.value as string // 如果是 where 函数,调用 where 过滤 if (name === 'where') { return this.where() } // 如果是 sum 求和函数,调用 sum 求和 if (name === 'sum') { return this.sum() } const objExp: Expression = this.children[0] as Expression // 获取对象 const obj: any = objExp.invoke() if (obj == null) { throw new ServiceException(`对象[${objExp.value}]为null`) } // 获得参数计算结果 const params: any[] = [] for (let i = 1; i < this.children.length; i++) { const paramExp: Expression = this.children[i] as Expression params.push(paramExp.invoke()) } if (name === 'runExpression') { const params1: string = params[0] params[0] = params1.replace('\'', '$') params.push(this.delegate?.getObjectNames()) } // 转换参数类型 const types: any[] = Array.from({ length: params.length }) for (let i = 0; i < params.length; i++) { const param = params[i] types[i] = param == null ? null : param.constructor } // 查找对象方法 const method = this.getMethod(obj, name, types) if (!method) { let error = `找不到方法: ${obj.constructor.name}.${name}(` // 添加方法参数 types.forEach((t) => { error += t ? `${t.name},` : 'null,' }) error += ')' throw new ServiceException(error) } // 调用方法并处理返回值 const oCall = method.apply(obj, params) if (oCall instanceof Promise) { return oCall.then(result => this.convert(result)) } else { return this.convert(oCall) } } /** * 查找与给定方法名和参数类型匹配的方法 */ private getMethod(obj: any, methodName: string, paramTypes: any[]): Function | null { // 获取对象自身的所有属性名 let methods = Object.getOwnPropertyNames(obj).filter(prop => typeof obj[prop] === 'function') // 获取对象的原型 let proto = Object.getPrototypeOf(obj) // 递归获取原型链上的所有方法 while (proto !== null) { methods = methods.concat( Object.getOwnPropertyNames(proto) .filter(prop => !['caller', 'callee', 'arguments'].includes(prop)) // 先排除 .filter((prop) => { try { return typeof proto[prop] === 'function' // 再判断是否为函数 } catch (e) { return false // 避免 TypeError } }), ) proto = Object.getPrototypeOf(proto) } // 去重 methods = [...new Set(methods)] for (const methodNameInObj of methods) { if (methodNameInObj === methodName) { const method = obj[methodNameInObj] if (this.matchParameterTypes(method, paramTypes)) { return method } } } return null } /** * 判断方法的参数类型是否与给定的类型匹配 */ private matchParameterTypes(method: Function, paramTypes: any[]): boolean { return true } public setDelegate(delegate: Delegate): void { this.delegate = delegate } private isNumberC(value: string): boolean { return !Number.isNaN(Number(value)) // 判断 value 是否可以转成有效的数字 } }