Support for Nested/Hierarchical Services
[sdc.git] / catalog-ui / src / app / ng2 / pages / composition / graph / utils / composition-graph-palette-utils.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 import {Injectable} from "@angular/core";
22 import {CompositionGraphGeneralUtils, RequirementAndCapabilities} from "./composition-graph-general-utils";
23 import {CommonGraphUtils} from "../common/common-graph-utils";
24 import {EventListenerService} from "../../../../../services/event-listener-service";
25 import {ResourceNamePipe} from "app/ng2/pipes/resource-name.pipe";
26 import {ComponentInstanceFactory} from "app/utils/component-instance-factory";
27 import {GRAPH_EVENTS, GraphUIObjects} from "app/utils/constants";
28 import {TopologyTemplateService} from "app/ng2/services/component-services/topology-template.service";
29 import {DndDropEvent} from "ngx-drag-drop/ngx-drag-drop";
30 import {SdcUiServices} from "onap-ui-angular"
31 import { Component as TopologyTemplate, NodesFactory, CapabilitiesGroup, RequirementsGroup,
32      CompositionCiNodeBase, ComponentInstance, LeftPaletteComponent, Point } from "app/models";
33 import {CompositionService} from "../../composition.service";
34 import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
35 import { QueueServiceUtils } from "app/ng2/utils/queue-service-utils";
36 import {ComponentGenericResponse} from "../../../../services/responses/component-generic-response";
37 import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requirement-utils";
38 import {CompositionGraphNodesUtils} from "./index";
39
40 @Injectable()
41 export class CompositionGraphPaletteUtils {
42
43     constructor(private generalGraphUtils:CompositionGraphGeneralUtils,
44                 private nodesFactory:NodesFactory,
45                 private commonGraphUtils:CommonGraphUtils,
46                 private queueServiceUtils:QueueServiceUtils,
47                 private eventListenerService:EventListenerService,
48                 private topologyTemplateService: TopologyTemplateService,
49                 private loaderService: SdcUiServices.LoaderService,
50                 private compositionService: CompositionService,
51                 private workspaceService: WorkspaceService,
52                 private matchCapabilitiesRequirementsUtils: MatchCapabilitiesRequirementsUtils,
53                 private nodesGraphUtils: CompositionGraphNodesUtils) {
54     }
55
56     /**
57      *
58      * @param Calculate matching nodes, highlight the matching nodes and fade the non matching nodes
59      * @param leftPaletteComponent
60      * @param _cy
61      * @returns void
62      * @private
63      */
64
65     public onComponentHoverIn = (leftPaletteComponent: LeftPaletteComponent, _cy: Cy.Instance) => {
66         const nodesData = this.nodesGraphUtils.getAllNodesData(_cy.nodes());
67         const nodesLinks = this.generalGraphUtils.getAllCompositionCiLinks(_cy);
68
69         if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(leftPaletteComponent.uniqueId)) {
70             const reqAndCap: RequirementAndCapabilities = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(leftPaletteComponent.uniqueId);
71             const filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodesToComponentInstance(
72                 { uniqueId: leftPaletteComponent.uniqueId, requirements: reqAndCap.requirements, capabilities: reqAndCap.capabilities} as ComponentInstance, nodesData, nodesLinks);
73
74             this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, _cy);
75             this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, _cy);
76         } else {
77
78             this.topologyTemplateService.getCapabilitiesAndRequirements(leftPaletteComponent.componentType, leftPaletteComponent.uniqueId).subscribe((response: ComponentGenericResponse) => {
79                 let reqAndCap: RequirementAndCapabilities = {
80                     capabilities: response.capabilities,
81                     requirements: response.requirements
82                 }
83                 this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, reqAndCap);
84             });
85         }
86     }
87
88     /**
89      * Calculate the dragged element (html element) position on canvas
90      * @param cy
91      * @param event
92      * @param position
93      * @returns {Cy.BoundingBox}
94      * @private
95      */
96     private _getNodeBBox(cy:Cy.Instance, event:DragEvent, position?:Cy.Position, eventPosition?: Point) {
97         let bbox = <Cy.BoundingBox>{};
98         if (!position) {
99             position = event ? this.commonGraphUtils.getCytoscapeNodePosition(cy, event) : eventPosition;
100         }
101         let cushionWidth:number = 40;
102         let cushionHeight:number = 40;
103
104         bbox.x1 = position.x - cushionWidth / 2;
105         bbox.y1 = position.y - cushionHeight / 2;
106         bbox.x2 = position.x + cushionWidth / 2;
107         bbox.y2 = position.y + cushionHeight / 2;
108         return bbox;
109     }
110
111     /**
112      * Create the component instance, update data from parent component in the left palette and notify on_insert_to_ucpe if component was dragg into ucpe
113      * @param cy
114      * @param fullComponent
115      * @param event
116      * @param component
117      */
118     private _createComponentInstanceOnGraphFromPaletteComponent(cy:Cy.Instance, fullComponent:LeftPaletteComponent, event:DragEvent) {
119         let componentInstanceToCreate:ComponentInstance = ComponentInstanceFactory.createComponentInstanceFromComponent(fullComponent, this.workspaceService.metadata.categories[0].useServiceSubstitutionForNestedServices); 
120         let cytoscapePosition:Cy.Position = this.commonGraphUtils.getCytoscapeNodePosition(cy, event);
121         componentInstanceToCreate.posX = cytoscapePosition.x;
122         componentInstanceToCreate.posY = cytoscapePosition.y;
123
124         let onFailedCreatingInstance:(error:any) => void = (error:any) => {
125             this.loaderService.deactivate();
126         };
127
128         //on success - update node data
129         let onSuccessCreatingInstance = (createInstance:ComponentInstance):void => {
130
131             this.loaderService.deactivate();
132             this.compositionService.addComponentInstance(createInstance);
133             createInstance.name = ResourceNamePipe.getDisplayName(createInstance.name);
134             createInstance.requirements = new RequirementsGroup(createInstance.requirements);
135             createInstance.capabilities = new CapabilitiesGroup(createInstance.capabilities);
136             createInstance.componentVersion = fullComponent.version;
137             createInstance.icon = fullComponent.icon;
138             createInstance.setInstanceRC();
139
140             let newNode:CompositionCiNodeBase = this.nodesFactory.createNode(createInstance);
141             this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, newNode);
142             this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CREATE_COMPONENT_INSTANCE);
143         };
144
145         this.queueServiceUtils.addBlockingUIAction(() => {
146             let uniqueId = this.workspaceService.metadata.uniqueId;
147             let componentType = this.workspaceService.metadata.componentType;
148             this.topologyTemplateService.createComponentInstance(componentType, uniqueId, componentInstanceToCreate).subscribe(onSuccessCreatingInstance, onFailedCreatingInstance);
149
150         });
151     }
152     //
153     // /**
154     //  * Thid function applay red/green background when component dragged from palette
155     //  * @param cy
156     //  * @param event
157     //  * @param dragElement
158     //  * @param dragComponent
159     //  */
160     // public onComponentDrag(cy:Cy.Instance, event) {
161     //     let draggedElement = document.getElementById("draggable_element");
162     //     // event.dataTransfer.setDragImage(draggableElement, 0, 0);
163     //     if (event.clientX < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || event.clientY < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
164     //         draggedElement.className = 'invalid-drag';
165     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
166     //         return;
167     //     }
168     //
169     //     let offsetPosition = {
170     //         x: event.clientX - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
171     //         y: event.clientY - GraphUIObjects.DIAGRAM_HEADER_OFFSET
172     //     };
173     //     let bbox = this._getNodeBBox(cy, event, offsetPosition);
174     //
175     //     if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
176     //         draggedElement.className = 'valid-drag';
177     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
178     //         // event.dataTransfer.setDragImage(draggedElement, 0, 0);
179     //         // event.dataTransfer.setDragImage(draggedElement, 0, 0);
180     //
181     //     } else {
182     //         draggedElement.className = 'invalid-drag';
183     //         event.dataTransfer.setDragImage(draggedElement.cloneNode(true), 0, 0);
184     //     }
185     // }
186
187     public isDragValid(cy:Cy.Instance, position: Point):boolean {
188         if (position.x < GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET || position.y < GraphUIObjects.DIAGRAM_HEADER_OFFSET) { //hovering over palette. Dont bother computing validity of drop
189             return false;
190         }
191         
192         let offsetPosition = {
193             x: position.x - GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET,
194             y: position.y - GraphUIObjects.DIAGRAM_HEADER_OFFSET
195         };
196         let bbox = this._getNodeBBox(cy, null, offsetPosition, position);
197
198         if (this.generalGraphUtils.isPaletteDropValid(cy, bbox)) {
199             return true;
200         } else {
201             return false;
202         }
203     } 
204     /**
205      *  This function is called when after dropping node on canvas
206      *  Check if the capability & requirements fulfilled and if not get from server
207      * @param cy
208      * @param dragEvent
209      * @param component
210      */
211     public addNodeFromPalette(cy:Cy.Instance, dragEvent:DndDropEvent) {
212         this.loaderService.activate();
213
214         let draggedComponent:LeftPaletteComponent = dragEvent.data;
215
216         if (this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(draggedComponent.uniqueId)) {
217             let fullComponent = this.generalGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(draggedComponent.uniqueId);
218             draggedComponent.capabilities = fullComponent.capabilities;
219             draggedComponent.requirements = fullComponent.requirements;
220             this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
221
222         } else {
223
224             this.topologyTemplateService.getFullComponent(draggedComponent.componentType, draggedComponent.uniqueId).subscribe((topologyTemplate:TopologyTemplate) => {
225                 draggedComponent.capabilities = topologyTemplate.capabilities;
226                 draggedComponent.requirements = topologyTemplate.requirements;
227                 this._createComponentInstanceOnGraphFromPaletteComponent(cy, draggedComponent, dragEvent.event);
228             });
229         }
230     }
231 }
232