import ELNode from "./type/ELNode"; import { ELStack } from "./ELStack"; import { GraphConfigData, NodeConfig } from "@logicflow/core"; import { ELType, GroupType } from "./type/ELType"; import MyParse from './MyParse'; interface TextEntity { x: number, y: number, value: string, } export default class MyContext { public endPoints: Record = {}; public sourceNum: Record = {}; private nodeMap: Record = {}; private inGrooupNode: Record = {}; public elStack: ELStack = new ELStack(); public startId: string = "start" public endId: string = "end"; public isEnd(id: string): boolean { return this.endId === id; } public isStart(id: string): boolean { return this.startId === id; } public getNodeById(id: string): ELNode { return this.nodeMap[id] } private initEdge(sourceId: string, endId: string, edgeText: string = "") { // 循环内外的连接不处理 if (this.inGrooupNode[sourceId] || this.inGrooupNode[endId]) return; if (!this.endPoints[sourceId]) { this.endPoints[sourceId] = []; } const node = this.nodeMap[endId] node.comingEdgeText = edgeText; this.endPoints[sourceId].push(node); if (!this.sourceNum[endId]) { this.sourceNum[endId] = 0; } this.sourceNum[endId]++; } public init(logicFlow: GraphConfigData) { const groupNode: NodeConfig[] = [] //初始化所有节点并转化为ElNode logicFlow.nodes.forEach(node => { if (!node.id) return; if (node.type === ELType.GROUP) { groupNode.push(node); return } this.initELNode(node); }) //最后处理所有的LOOP节点 groupNode.forEach(node => { this.initLoopELNode(node); }) // 初始化start和end节点 const start: ELNode = new ELNode(); start.id = this.startId; this.nodeMap[this.startId] = start; const end: ELNode = new ELNode(); end.id = this.endId; this.nodeMap[this.endId] = end; //遍历边 logicFlow.edges.forEach(edge => { const sourceId = edge.sourceNodeId const targetId = edge.targetNodeId if (!sourceId || !targetId) return; //if节点特殊处理 if (this.nodeMap[sourceId].type === ELType.IF) this.parseIFEdge((edge.text as TextEntity)?.value, sourceId, targetId); else this.initEdge(sourceId, targetId, (edge.text as TextEntity)?.value); }) //检查节点,没有起点的连接到start,没有终点的连接到end logicFlow.nodes.forEach(node => { if (!node.id || this.inGrooupNode[node.id]) return; if (!this.endPoints[node.id]) { this.initEdge(node.id, this.endId); } if (!this.sourceNum[node.id]) { this.initEdge(this.startId, node.id); } // 对于IF节点,如果只有一条边,添加边 if (node.type == ELType.IF) { this.endPoints[node.id].forEach((end, index) => { if (!end) { // 添加一条边指向end this.endPoints[node.id!][index] = this.getNodeById(this.endId); this.sourceNum[this.endId]++; } }) } }) //没有节点时,只有start和end if (logicFlow.nodes.length === 0) { this.initEdge(this.startId, this.endId); } } /** * 保证IF节点一定有两个分支,尽管可能有undefined * 且true分支在前,false分支在后 * @param text * @param sourceId * @param targetId * @private */ private parseIFEdge(text: string, sourceId: string, targetId: string) { const target = this.nodeMap[targetId]; let ends = this.endPoints[sourceId]; //@ts-ignore if (!ends) ends = [undefined, undefined]; if (this.isTrueText(text)) { if (ends[0]) ends[1] = ends[0]; ends[0] = target; } else if (this.isFalseText(text)) { if (ends[1]) ends[0] = ends[1]; ends[1] = target; } else { if (!ends[0]) ends[0] = target; else ends[1] = target; } this.endPoints[sourceId] = ends; if (!this.sourceNum[targetId]) { this.sourceNum[targetId] = 0; } this.sourceNum[targetId]++; } private isTrueText(text: string): boolean { const texts = ["是", "true", "True", "TRUE"]; return !!texts.find(t => t === text); } private isFalseText(text: string): boolean { const texts = ["否", "false", "False", "FALSE"]; return !!texts.find(t => t === text); } /** * 将logicFlow节点转化为ELNode * * @param lfNode Lf节点 * @return {@link ELNode} */ private initELNode(lfNode: NodeConfig): ELNode { const node: ELNode = new ELNode(); node.id = lfNode.id as string; node.type = this.typeFormat(lfNode.type); node.properties = lfNode.properties; node.nodeId = lfNode.properties?.nodeId as string; node.name = lfNode.properties?.name as string; node.groupType = lfNode.properties?.groupType as GroupType; node.data = lfNode.properties?.data as string; node.aliasId = lfNode.properties?.aliasId as string; node.tag = lfNode.properties?.tag as string; node.startNum = lfNode.properties?.startNum as number; this.nodeMap[node.id] = node; return node; } /** * 处理 Group节点 * * @param lfNode Lf节点 * @return {@link ELNode} */ private initLoopELNode(lfNode: NodeConfig) { const node: ELNode = this.initELNode(lfNode); if (node.groupType == GroupType.LOGIC) { //logic节点单独解析 node.elString = this.getLogicStr(lfNode.flowData) } else { node.addChild( //@ts-ignore new MyParse(lfNode.flowData).parse() ); } this.nodeMap[node.id] = node; // 标记内部节点不需要再次处理了 //@ts-ignore lfNode.flowData.nodes.forEach(node => { const id = node.id as string; this.inGrooupNode[id] = true; }); // 将连接到GROUP内部的边连接到GROUP //@ts-ignore lfNode.sourceNodeIds?.forEach(id => { this.initEdge(id, node.id) }) //@ts-ignore lfNode.targetNodeIds?.forEach(id => { this.initEdge(node.id, id) }) } private typeFormat(lfType: string): ELType { if (lfType === "IF") return ELType.IF; if (lfType === "SWITCH") return ELType.SWITCH; if (lfType === "GROUP") return ELType.GROUP; if (lfType === "AND") return ELType.AND; if (lfType === "NOT") return ELType.NOT; if (lfType === "OR") return ELType.OR; return lfType as ELType; } public setSourceNum(node: ELNode, num: number) { this.sourceNum[node.id] = num; } public getSourceNum(node: ELNode) { const num = this.sourceNum[node.id] if (!num) return 0; return num; } public getEndNum(node: ELNode): number { const elNodes = this.endPoints[node.id] if (!elNodes) return 0; return elNodes.length; } public getEndList(node: ELNode): ELNode[] { let elNodes = this.endPoints[node.id]; if (!elNodes) return []; return elNodes; } public push(node: ELNode) { this.elStack.push(node); } public pop(): ELNode { return this.elStack.pop(); } /** * 创建一个类似函数的栈环境 * @param node */ public createStackEnv(node: ELNode) { this.elStack.create(); const newNode = new ELNode() newNode.id = node.id; newNode.type = node.type newNode.groupType = node.groupType newNode.aliasId = node.aliasId newNode.name = node.name newNode.data = node.data newNode.tag = node.tag newNode.nodeId = node.nodeId newNode.child = node.child newNode.comingEdgeText = node.comingEdgeText newNode.elString = node.elString //group专用 newNode.startNode = node.startNode newNode.breakNode = node.breakNode newNode.exceptionNode = node.exceptionNode newNode.startNum = node.startNum this.elStack.push(newNode); } /** * 退出当前栈空间 * @returns 下次分析的开始节点 */ public quitStackEnv() { return this.elStack.quit(); } public setStackEndPoint(node: ELNode) { this.elStack.addEndPoint(node); } /** * * @param logicFlow logicGroup 的内部节点和边 * @returns */ private getLogicStr(logicFlow: GraphConfigData): string { const nodeMap: Record = {} logicFlow.nodes.forEach(n => nodeMap[n.id!] = n) const targetNumMap = {} //每个节点的后继数量 logicFlow.edges.forEach(e => { if (!targetNumMap[e.sourceNodeId]) { targetNumMap[e.sourceNodeId] = 1 } else { targetNumMap[e.sourceNodeId]++ } }) // 查找后继数量为 0 的第一个节点 ID const firstZeroSuccessorNodeId = logicFlow.nodes.map(n => n.id!).find(id => !targetNumMap[id]); const getStr = (id: string) => { const node = nodeMap[id]; //所有source节点 const startIds = logicFlow.edges.filter(e => e.targetNodeId === id).map(e => e.sourceNodeId); const joins = startIds.map(id => { const n = nodeMap[id] if (n.type === ELType.ID) { return n.properties?.nodeId; } if (n.type === ELType.AND || n.type === ELType.OR || n.type === ELType.NOT) { return getStr(n.id!) } throw new Error("未知的节点类型") }).join(",") return `${node.type}(${joins})` } return getStr(firstZeroSuccessorNodeId!); } }