rest task's parameters can quote output parameter of previous rest tasks.
Issue-ID: SDC-121
Change-Id: I94f2058f7b8b2ad600ffb99c8838b37da5bb5b9d
Signed-off-by: Lvbo163 <lv.bo163@zte.com.cn>
import { ParameterTreeComponent } from "./components/parameter-tree/parameter-tree.component";
import { EditablePropertyComponent } from "./components/editable-property/editable-property.component";
import { SwaggerTreeConverterService } from "./services/swagger-tree-converter.service";
+import { WorkflowProcessService } from "./services/workflow-process.service";
@NgModule({
declarations: [
JsPlumbService,
SwaggerTreeConverterService,
WorkflowConfigService,
+ WorkflowProcessService,
WorkflowService
],
bootstrap: [AppComponent]
}
private formatParam(params: any[]): void {
- console.log(params);
params.forEach(param => this.initParam(param));
}
constructor(private dataAccessService: DataAccessService) { }\r
\r
public ngOnInit(): void {\r
- console.log(this.planItems);\r
if (1 === this.valueSource.length) {\r
this.showValueSource = false;\r
}\r
import { WorkflowNode } from '../../model/workflow/workflow-node';
import { BroadcastService } from '../../services/broadcast.service';
import { JsPlumbService } from '../../services/jsplumb.service';
-import { WorkflowService } from '../../services/workflow.service';
import { PlanTreeviewItem } from "../../model/plan-treeview-item";
+import { WorkflowProcessService } from "../../services/workflow-process.service";
/**
* property component presents information of a workflow node.
constructor(private broadcastService: BroadcastService,
private jsPlumnService: JsPlumbService,
- private workflowService: WorkflowService) {
+ private processService: WorkflowProcessService) {
}
this.broadcastService.showProperty$.subscribe(show => this.show = show);
this.broadcastService.nodeProperty$.subscribe(node => {
this.node = node;
- this.planItems = this.workflowService.getPlanParameters(this.node.id);
+ this.planItems = this.processService.getPlanParameters(this.node.id);
});
}
this.show = false;
this.jsPlumnService.remove(this.node.id);
- this.workflowService.deleteNode(this.node.id);
+ this.processService.deleteNode(this.node.id);
}
}
\r
import { Injectable } from '@angular/core';\r
import * as jsp from 'jsplumb';\r
-import { WorkflowService } from "./workflow.service";\r
+import { WorkflowProcessService } from "./workflow-process.service";\r
\r
/**\r
* JsPlumbService\r
export class JsPlumbService {\r
public jsplumbInstance;\r
\r
- constructor(private workflowService: WorkflowService) {\r
+ constructor(private processService: WorkflowProcessService) {\r
this.initJsPlumbInstance();\r
}\r
\r
\r
// add connection to model data while a new connection is build\r
this.jsplumbInstance.bind('connection', info => {\r
- this.workflowService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);\r
+ this.processService.addSequenceFlow(info.connection.sourceId, info.connection.targetId);\r
\r
info.connection.bind('click', connection => {\r
this.jsplumbInstance.select({ connections: [connection] }).delete();\r
- this.workflowService.deleteSequenceFlow(connection.sourceId, connection.targetId);\r
+ this.processService.deleteSequenceFlow(connection.sourceId, connection.targetId);\r
});\r
});\r
\r
const left = event.e.clientX - 220 - (event.e.offsetX / 2);\r
const top = event.e.clientY - 70 - (event.e.offsetY / 2);\r
\r
- this.workflowService.addNode(type, type, top, left);\r
+ this.processService.addNode(type, type, top, left);\r
},\r
});\r
}\r
--- /dev/null
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ * ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { Injectable } from '@angular/core';\r
+import { WorkflowNode } from "../model/workflow/workflow-node";\r
+import { Workflow } from "../model/workflow/workflow";\r
+import { Position } from "../model/workflow/position";\r
+import { NodeType } from "../model/workflow/node-type.enum";\r
+import { StartEvent } from "../model/workflow/start-event";\r
+import { SequenceFlow } from "../model/workflow/sequence-flow";\r
+import { RestTask } from "../model/workflow/rest-task";\r
+import { PlanTreeviewItem } from "../model/plan-treeview-item";\r
+import { WorkflowConfigService } from "./workflow-config.service";\r
+import { Swagger, SwaggerModelSimple, SwaggerReferenceObject } from "../model/swagger";\r
+import { WorkflowService } from "./workflow.service";\r
+\r
+/**\r
+ * WorkflowService\r
+ * provides all of the operations about workflow operations.\r
+ */\r
+@Injectable()\r
+export class WorkflowProcessService {\r
+\r
+ constructor(private workflowService: WorkflowService, private configService: WorkflowConfigService) {\r
+\r
+ }\r
+\r
+ public getProcess(): WorkflowNode[] {\r
+ return this.workflowService.workflow.nodes;\r
+ }\r
+\r
+ public addNode(name: string, type: string, top: number, left: number): WorkflowNode {\r
+ let node: WorkflowNode;\r
+ switch (type) {\r
+ case NodeType[NodeType.startEvent]:\r
+ node = new StartEvent(this.createId(), name, type, new Position(top, left), []);\r
+ break;\r
+ case NodeType[NodeType.restTask]:\r
+ node = new RestTask(this.createId(), name, type, new Position(top, left), []);\r
+ break;\r
+ default:\r
+ node = new WorkflowNode(this.createId(), name, type, new Position(top, left), []);\r
+ break;\r
+ }\r
+\r
+ this.getProcess().push(node);\r
+ return node;\r
+ }\r
+\r
+ public deleteNode(nodeId: string): WorkflowNode {\r
+ // delete related connections\r
+ this.getProcess().forEach(node => this.deleteSequenceFlow(node.id, nodeId));\r
+\r
+ // delete current node\r
+ const index = this.getProcess().findIndex(node => node.id === nodeId);\r
+ if (index !== -1) {\r
+ const node = this.getProcess().splice(index, 1)[0];\r
+ node.sequenceFlows = [];\r
+ return node;\r
+ }\r
+\r
+ return undefined;\r
+ }\r
+\r
+ public addSequenceFlow(sourceId: string, targetId: string) {\r
+ const node = this.getNodeById(sourceId);\r
+ if (node) {\r
+ const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
+ if (index === -1) {\r
+ node.sequenceFlows.push(new SequenceFlow(sourceId, targetId));\r
+ }\r
+ }\r
+ }\r
+\r
+ public deleteSequenceFlow(sourceId: string, targetId: string) {\r
+ const node = this.getNodeById(sourceId);\r
+ if (node) {\r
+ const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
+ if (index !== -1) {\r
+ node.sequenceFlows.splice(index, 1);\r
+ }\r
+ }\r
+ }\r
+\r
+ public getPlanParameters(nodeId: string): PlanTreeviewItem[] {\r
+ const preNodeList = new Array<WorkflowNode>();\r
+ this.getPreNodes(nodeId, preNodeList);\r
+\r
+ return this.loadNodeOutputs(preNodeList);\r
+ }\r
+\r
+ private loadNodeOutputs(nodes: WorkflowNode[]): PlanTreeviewItem[] {\r
+ const params = new Array<PlanTreeviewItem>();\r
+ nodes.forEach(node => {\r
+ switch (node.type) {\r
+ case NodeType[NodeType.startEvent]:\r
+ params.push(this.loadOutput4StartEvent(<StartEvent>node));\r
+ break;\r
+ case NodeType[NodeType.restTask]:\r
+ params.push(this.loadOutput4RestTask(<RestTask>node));\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ });\r
+\r
+ return params;\r
+ }\r
+\r
+ private loadOutput4StartEvent(node: StartEvent): PlanTreeviewItem {\r
+ const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, []);\r
+ node.parameters.map(param =>\r
+ startItem.children.push(new PlanTreeviewItem(param.name, `[${param.name}]`, [])));\r
+ return startItem;\r
+ }\r
+\r
+ private loadOutput4RestTask(node: RestTask): PlanTreeviewItem {\r
+ const item = new PlanTreeviewItem(node.name, `[${node.id}]`, []);\r
+ item.children.push(this.createStatusCodeTreeViewItem(node.id));\r
+\r
+ if (node.responses.length !== 0) { // load rest responses\r
+ const responseItem = this.createResponseTreeViewItem(node.id);\r
+ item.children.push(responseItem);\r
+ if (node.responses[0]) {\r
+ const swagger = this.configService.getSwaggerInfo(node.serviceName, node.serviceVersion);\r
+ const swaggerDefinition = this.configService.getDefinition(swagger, node.responses[0].schema.$ref);\r
+ this.loadParamsBySwaggerDefinition(responseItem, swagger, <SwaggerModelSimple>swaggerDefinition);\r
+ }\r
+ }\r
+\r
+ return item;\r
+ }\r
+\r
+ private createStatusCodeTreeViewItem(nodeId: string): PlanTreeviewItem {\r
+ return new PlanTreeviewItem('statusCode', `[${nodeId}].[statusCode]`, []);\r
+ }\r
+\r
+ private createResponseTreeViewItem(nodeId: string): PlanTreeviewItem {\r
+ return new PlanTreeviewItem('response', `[${nodeId}].[responseBody]`, []);\r
+ }\r
+\r
+ private loadParamsBySwaggerDefinition(parentItem: PlanTreeviewItem, swagger: Swagger, definition: SwaggerModelSimple) {\r
+ Object.getOwnPropertyNames(definition.properties).map(key => {\r
+ const property = definition.properties[key];\r
+ const value = `${parentItem.value}.[${key}]`;\r
+ const propertyItem = new PlanTreeviewItem(key, value, []);\r
+ parentItem.children.push(propertyItem);\r
+\r
+ if (property instanceof SwaggerReferenceObject) {\r
+ const propertyDefinition = this.configService.getDefinition(swagger, property.$ref);\r
+ this.loadParamsBySwaggerDefinition(propertyItem, swagger,\r
+ <SwaggerModelSimple>propertyDefinition);\r
+ }\r
+\r
+ return propertyItem;\r
+ });\r
+ }\r
+\r
+ public getPreNodes(nodeId: string, preNodes: WorkflowNode[]) {\r
+ const preNode4CurrentNode = [];\r
+ this.getProcess().forEach(node => {\r
+ if (this.isPreNode(node, nodeId)) {\r
+ const existNode = preNodes.find(tmpNode => tmpNode.id === node.id);\r
+ if (existNode) {\r
+ // current node already exists in preNodes. this could avoid loop circle.\r
+ } else {\r
+ preNode4CurrentNode.push(node);\r
+ preNodes.push(node);\r
+ }\r
+ }\r
+ });\r
+\r
+ preNode4CurrentNode.forEach(node => this.getPreNodes(node.id, preNodes));\r
+ }\r
+\r
+ public isPreNode(preNode: WorkflowNode, id: string): boolean {\r
+ const targetNode = preNode.sequenceFlows.find(connection => connection.targetRef === id);\r
+ return targetNode !== undefined;\r
+ }\r
+\r
+ public getNodeById(sourceId: string): WorkflowNode {\r
+ return this.getProcess().find(node => node.id === sourceId);\r
+ }\r
+\r
+ private createId() {\r
+ const idSet = new Set();\r
+ this.getProcess().forEach(node => idSet.add(node.id));\r
+\r
+ for (let i = 0; i < idSet.size; i++) {\r
+ if (!idSet.has('node' + i)) {\r
+ return 'node' + i;\r
+ }\r
+ }\r
+\r
+ return 'node' + idSet.size;\r
+ }\r
+}\r
*/\r
\r
import { Injectable } from '@angular/core';\r
-import { WorkflowNode } from "../model/workflow/workflow-node";\r
import { DataAccessService } from "./data-access/data-access.service";\r
import { Observable } from "rxjs/Observable";\r
import { Workflow } from "../model/workflow/workflow";\r
-import { Position } from "../model/workflow/position";\r
-import { NodeType } from "../model/workflow/node-type.enum";\r
-import { StartEvent } from "../model/workflow/start-event";\r
-import { SequenceFlow } from "../model/workflow/sequence-flow";\r
-import { RestTask } from "../model/workflow/rest-task";\r
-import { PlanTreeviewItem } from "../model/plan-treeview-item";\r
\r
/**\r
* WorkflowService\r
console.log(this.workflow);\r
return this.dataAccessService.catalogService.saveWorkflow(this.workflow);\r
}\r
-\r
- public addNode(name: string, type: string, top: number, left: number): WorkflowNode {\r
- let node: WorkflowNode;\r
- switch (type) {\r
- case NodeType[NodeType.startEvent]:\r
- node = new StartEvent(this.createId(), name, type, new Position(top, left), []);\r
- break;\r
- case NodeType[NodeType.restTask]:\r
- node = new RestTask(this.createId(), name, type, new Position(top, left), []);\r
- break;\r
- default:\r
- node = new WorkflowNode(this.createId(), name, type, new Position(top, left), []);\r
- break;\r
- }\r
-\r
- this.workflow.nodes.push(node);\r
- return node;\r
- }\r
-\r
- public deleteNode(nodeId: string): WorkflowNode {\r
- // delete related connections\r
- this.workflow.nodes.forEach(node => this.deleteSequenceFlow(node.id, nodeId));\r
-\r
- // delete current node\r
- const index = this.workflow.nodes.findIndex(node => node.id === nodeId);\r
- if (index !== -1) {\r
- const node = this.workflow.nodes.splice(index, 1)[0];\r
- node.sequenceFlows = [];\r
- return node;\r
- }\r
-\r
- return undefined;\r
- }\r
-\r
- public addSequenceFlow(sourceId: string, targetId: string) {\r
- const node = this.getNodeById(sourceId);\r
- if (node) {\r
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
- if (index === -1) {\r
- node.sequenceFlows.push(new SequenceFlow(sourceId, targetId));\r
- }\r
- }\r
- }\r
-\r
- public deleteSequenceFlow(sourceId: string, targetId: string) {\r
- const node = this.getNodeById(sourceId);\r
- if (node) {\r
- const index = node.sequenceFlows.findIndex(sequenceFlow => sequenceFlow.targetRef === targetId);\r
- if (index !== -1) {\r
- node.sequenceFlows.splice(index, 1);\r
- }\r
- }\r
- }\r
-\r
- public getPlanParameters(nodeId: string): PlanTreeviewItem[] {\r
- const preNodeList = new Array<WorkflowNode>();\r
- this.getPreNodes(nodeId, preNodeList);\r
-\r
- return this.loadNodeOutputs(preNodeList);\r
- }\r
-\r
- private loadNodeOutputs(nodes: WorkflowNode[]): PlanTreeviewItem[] {\r
- const params = new Array<PlanTreeviewItem>();\r
- nodes.forEach(node => {\r
- switch (node.type) {\r
- case NodeType[NodeType.startEvent]:\r
- params.push(this.loadOutput4StartEvent(<StartEvent>node));\r
- break;\r
- case NodeType[NodeType.restTask]:\r
- // TODO for rest task\r
- break;\r
- default:\r
- break;\r
- }\r
- });\r
-\r
- return params;\r
- }\r
-\r
- private loadOutput4StartEvent(node: StartEvent): PlanTreeviewItem {\r
- const startItem = new PlanTreeviewItem(node.name, `[${node.id}]`, []);\r
- node.parameters.map(param =>\r
- startItem.children.push(new PlanTreeviewItem(param.name, `[${param.name}]`, [])));\r
- return startItem;\r
- }\r
-\r
- public getPreNodes(nodeId: string, preNodes: WorkflowNode[]) {\r
- const preNode4CurrentNode = [];\r
- this.workflow.nodes.forEach(node => {\r
- if (this.isPreNode(node, nodeId)) {\r
- const existNode = preNodes.find(tmpNode => tmpNode.id === node.id);\r
- if (existNode) {\r
- // current node already exists in preNodes. this could avoid loop circle.\r
- } else {\r
- preNode4CurrentNode.push(node);\r
- preNodes.push(node);\r
- }\r
- }\r
- });\r
-\r
- preNode4CurrentNode.forEach(node => this.getPreNodes(node.id, preNodes));\r
- }\r
-\r
- public isPreNode(preNode: WorkflowNode, id: string): boolean {\r
- const targetNode = preNode.sequenceFlows.find(connection => connection.targetRef === id);\r
- return targetNode !== undefined;\r
- }\r
-\r
- public getNodeById(sourceId: string): WorkflowNode {\r
- return this.workflow.nodes.find(node => node.id === sourceId);\r
- }\r
-\r
- private createId() {\r
- const idSet = new Set();\r
- this.workflow.nodes.forEach(node => idSet.add(node.id));\r
-\r
- for (let i = 0; i < idSet.size; i++) {\r
- if (!idSet.has('node' + i)) {\r
- return 'node' + i;\r
- }\r
- }\r
-\r
- return 'node' + idSet.size;\r
- }\r
}\r