support quote output of rest task 69/10669/1
authorLvbo163 <lv.bo163@zte.com.cn>
Thu, 7 Sep 2017 02:02:49 +0000 (10:02 +0800)
committerLvbo163 <lv.bo163@zte.com.cn>
Thu, 7 Sep 2017 02:02:49 +0000 (10:02 +0800)
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>
sdc-workflow-designer-ui/src/app/app.module.ts
sdc-workflow-designer-ui/src/app/components/parameter-tree/parameter-tree.component.ts
sdc-workflow-designer-ui/src/app/components/parameter/parameter.component.ts
sdc-workflow-designer-ui/src/app/components/property/properties.component.ts
sdc-workflow-designer-ui/src/app/services/jsplumb.service.ts
sdc-workflow-designer-ui/src/app/services/workflow-process.service.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/workflow.service.ts

index 0bf4b14..047f468 100644 (file)
@@ -42,6 +42,7 @@ import { RestTaskParametersComponent } from "./components/property/rest-task/res
 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: [
@@ -85,6 +86,7 @@ import { SwaggerTreeConverterService } from "./services/swagger-tree-converter.s
         JsPlumbService,
         SwaggerTreeConverterService,
         WorkflowConfigService,
+        WorkflowProcessService,
         WorkflowService
     ],
     bootstrap: [AppComponent]
index d0e04e3..0de35b9 100644 (file)
@@ -186,7 +186,6 @@ export class ParameterTreeComponent implements OnChanges {
     }
 
     private formatParam(params: any[]): void {
-        console.log(params);
         params.forEach(param => this.initParam(param));
     }
 
index 2cd5a0f..3539c8f 100644 (file)
@@ -45,7 +45,6 @@ export class ParameterComponent implements OnInit {
     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
index f3f784a..2aa552e 100644 (file)
@@ -15,8 +15,8 @@ import { AfterViewInit, Component } from '@angular/core';
 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.
@@ -36,7 +36,7 @@ export class PropertiesComponent implements AfterViewInit {
 
     constructor(private broadcastService: BroadcastService,
                 private jsPlumnService: JsPlumbService,
-                private workflowService: WorkflowService) {
+                private processService: WorkflowProcessService) {
 
     }
 
@@ -44,7 +44,7 @@ export class PropertiesComponent implements AfterViewInit {
         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);
         });
     }
 
@@ -57,6 +57,6 @@ export class PropertiesComponent implements AfterViewInit {
         this.show = false;
 
         this.jsPlumnService.remove(this.node.id);
-        this.workflowService.deleteNode(this.node.id);
+        this.processService.deleteNode(this.node.id);
     }
 }
index ffd00c6..543b09f 100644 (file)
@@ -12,7 +12,7 @@
 \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
@@ -22,7 +22,7 @@ import { WorkflowService } from "./workflow.service";
 export class JsPlumbService {\r
     public jsplumbInstance;\r
 \r
-    constructor(private workflowService: WorkflowService) {\r
+    constructor(private processService: WorkflowProcessService) {\r
         this.initJsPlumbInstance();\r
     }\r
 \r
@@ -58,11 +58,11 @@ export class JsPlumbService {
 \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
@@ -117,7 +117,7 @@ export class JsPlumbService {
                 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
diff --git a/sdc-workflow-designer-ui/src/app/services/workflow-process.service.ts b/sdc-workflow-designer-ui/src/app/services/workflow-process.service.ts
new file mode 100644 (file)
index 0000000..4c701ec
--- /dev/null
@@ -0,0 +1,206 @@
+/**\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
index 4bcd43b..7d75192 100644 (file)
  */\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
@@ -39,128 +32,4 @@ export class WorkflowService {
         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