9fab0da7eeb6a38f40a325bfca3df9f5d9ed6065
[osm/NG-UI.git] / src / app / packages / ns-packages / vnf-composer / VNFComposerComponent.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17  */
18 /**
19  * @file VNFComposerComponent
20  */
21 import { HttpHeaders } from '@angular/common/http';
22 import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
23 import { ActivatedRoute, Router } from '@angular/router';
24 import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
25 import { TranslateService } from '@ngx-translate/core';
26 import { NotifierService } from 'angular-notifier';
27 import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
28 import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
29 import * as d3 from 'd3';
30 import { DataService } from 'DataService';
31 import { environment } from 'environment';
32 import * as HttpStatus from 'http-status-codes';
33 import * as jsyaml from 'js-yaml';
34 import { RestService } from 'RestService';
35 import { SharedService, isNullOrUndefined } from 'SharedService';
36 import { COMPOSERNODES, EXTCPD, GRAPHDETAILS, INTCPD, IVLD, Tick, TickPath, VDU, VDUINTCPD, VNFD, VNFDATA, VNIR } from 'VNFDModel';
37
38 /**
39  * Creating component
40  * @Component takes VNFComposerComponent.html as template url
41  */
42 @Component({
43   templateUrl: './VNFComposerComponent.html',
44   styleUrls: ['./VNFComposerComponent.scss'],
45   encapsulation: ViewEncapsulation.None
46 })
47 /** Exporting a class @exports VNFComposerComponent */
48 export class VNFComposerComponent {
49   /** To inject services @public */
50   public injector: Injector;
51   /** View child contains graphContainer ref @public  */
52   @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
53   /** dataService to pass the data from one component to another @public */
54   public dataService: DataService;
55   /** random number count @public */
56   public randomNumberLength: number;
57   /** Contains the vnfd information @public */
58   public vnfList: string[] = [];
59   /** Contains VNFD Information @public */
60   public vnfdInfo: VNFD = { 'product-name': '', description: '', version: '', id: '', provider: '' };
61   /** Contains right panel box information @public */
62   public showRightSideInfo: string = '';
63   /** Add the fixed class for the freeze @public */
64   public fixedClass: string = 'fixed';
65   /** Check the loading results @public */
66   public isLoadingResults: boolean = true;
67   /** Give the message for the loading @public */
68   public message: string = 'PLEASEWAIT';
69   /** Assign the forcesimulation active @public */
70   public forceSimulationActive: boolean = false;
71   /** Assign pinned class for the button when freezed @public */
72   public classApplied: boolean = false;
73   /** Contains sidebar open status @public */
74   public sideBarOpened: boolean = false;
75   /** Contains SVG attributes @private */
76   // eslint-disable-next-line @typescript-eslint/no-explicit-any
77   private svg: any;
78   /** Contains forced node animations @private */
79   // eslint-disable-next-line @typescript-eslint/no-explicit-any
80   private force: any;
81   /** Contains the Drag line */
82   // eslint-disable-next-line @typescript-eslint/no-explicit-any
83   private dragLine: any;
84   /** Contains id of the node @private */
85   private identifier: string;
86   /** Contains path information of the node */
87   // eslint-disable-next-line @typescript-eslint/no-explicit-any
88   private path: any;
89   /** Contains node network @private */
90   // eslint-disable-next-line @typescript-eslint/no-explicit-any
91   private network: any;
92   /** Contains node network @private */
93   // eslint-disable-next-line @typescript-eslint/no-explicit-any
94   private virutualDeploymentUnit: any;
95   /** Contains node connectionPoint @private */
96   // eslint-disable-next-line @typescript-eslint/no-explicit-any
97   private connectionPoint: any;
98   /** Contains node intConnectionPoint @private */
99   // eslint-disable-next-line @typescript-eslint/no-explicit-any
100   private intConnectionPoint: any;
101   /** Contains the node information @private */
102   private nodes: COMPOSERNODES[] = [];
103   /** Contains the link information of nodes @private */
104   private links: {}[] = [];
105   /** Instance of the rest service @private */
106   private restService: RestService;
107   /** Service holds the router information @private */
108   private router: Router;
109   /** Service contails all the shared service information @private */
110   private sharedService: SharedService;
111   /** Holds teh instance of AuthService class of type AuthService @private */
112   private activatedRoute: ActivatedRoute;
113   /** Notifier service to popup notification @private */
114   private notifierService: NotifierService;
115   /** Controls the header form @private */
116   private headers: HttpHeaders;
117   /** Contains tranlsate instance @private */
118   private translateService: TranslateService;
119   /** Rendered nodes represent network @private */
120   // eslint-disable-next-line @typescript-eslint/no-explicit-any
121   private gNetwork: any;
122   /** Rendered nodes represent VDU @private */
123   // eslint-disable-next-line @typescript-eslint/no-explicit-any
124   private gVirutualDeploymentUnit: any;
125   /** Rendered nodes represent connection point @private */
126   // eslint-disable-next-line @typescript-eslint/no-explicit-any
127   private gConnectionPoint: any;
128   /** Rendered nodes represent internal connection point @private */
129   // eslint-disable-next-line @typescript-eslint/no-explicit-any
130   private gIntConnectionPoint: any;
131   /** Contains all the information about VNF Details @private */
132   private vnfdPackageDetails: VNFD;
133   /** Conatins mousedown action @private */
134   private mousedownNode: COMPOSERNODES = null;
135   /** Conatins mouseup action @private */
136   private mouseupNode: COMPOSERNODES = null;
137   /** Conatins current Selection node action @private */
138   private currentSelectedNode: COMPOSERNODES = null;
139   /** Add the activeNode for the selected @private */
140   private activeNode: string = 'active';
141   /** Contains lastkeypressed instance @private */
142   private lastKeyDown: number = -1;
143   /** Contains VDU Information @private */
144   private vduInfo: VDU;
145   /** Contains VDU Old value Information @private */
146   private oldVDUID: string;
147   /** Contains Internal VL Information @private */
148   private intvlInfo: IVLD;
149   /** Contains Internal VL Old value Information @private */
150   private oldintVLID: string;
151   /** Contains Connection Point Information @private */
152   private cpInfo: EXTCPD;
153   /** Contains Connection Point Old value Information @private */
154   private oldCPID: string;
155   /** Contains Internal Connection Point Information @private */
156   private intcpInfo: VNIR;
157   /** Instance of the modal service @private */
158   private modalService: NgbModal;
159
160   constructor(injector: Injector) {
161     this.injector = injector;
162     this.restService = this.injector.get(RestService);
163     this.dataService = this.injector.get(DataService);
164     this.router = this.injector.get(Router);
165     this.activatedRoute = this.injector.get(ActivatedRoute);
166     this.notifierService = this.injector.get(NotifierService);
167     this.translateService = this.injector.get(TranslateService);
168     this.sharedService = this.injector.get(SharedService);
169     this.modalService = this.injector.get(NgbModal);
170   }
171   /**
172    * Lifecyle Hooks the trigger before component is instantiate
173    */
174   public ngOnInit(): void {
175     this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
176     this.generateData();
177     this.headers = new HttpHeaders({
178       'Content-Type': 'application/gzip',
179       Accept: 'application/json',
180       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
181     });
182   }
183
184   /** Prepare information for node creation of VNFD @public */
185   public generateData(): void {
186     this.nodes = []; this.links = []; this.vnfdPackageDetails = null;
187     this.showRightSideInfo = 'vnfdInfo';
188     this.restService.getResource(environment.VNFPACKAGESCONTENT_URL + '/' + this.identifier)
189       .subscribe((vnfdPackageDetails: VNFD): void => {
190         try {
191           delete vnfdPackageDetails._admin;
192           delete vnfdPackageDetails._id;
193           delete vnfdPackageDetails._links;
194           this.vnfdPackageDetails = vnfdPackageDetails;
195           this.generateVDU(vnfdPackageDetails);
196           this.generateCPPoint(vnfdPackageDetails);
197           this.generateInternalVLD(vnfdPackageDetails);
198           this.generateInternalCP(vnfdPackageDetails);
199           this.generateIntVLCPLinks(vnfdPackageDetails);
200           this.generateVDUCPLinks(vnfdPackageDetails);
201           this.createNode(this.nodes);
202           this.generateVNFInfo(vnfdPackageDetails);
203         } catch (e) {
204           this.notifierService.notify('error', this.translateService.instant('ERROR'));
205         }
206         this.isLoadingResults = false;
207       }, (error: ERRORDATA): void => {
208         error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
209         if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
210           this.router.navigateByUrl('404', { skipLocationChange: true }).catch((): void => {
211             // Catch Navigation Error
212         });
213         } else {
214           this.restService.handleError(error, 'get');
215         }
216         this.isLoadingResults = false;
217         this.showRightSideInfo = '';
218       });
219   }
220   /** Generate the VNF Package Information */
221   public generateVNFInfo(vnfdPackageDetails: VNFD): void {
222     this.vnfdInfo['product-name'] = vnfdPackageDetails['product-name'];
223     this.vnfdInfo.description = vnfdPackageDetails.description;
224     this.vnfdInfo.version = vnfdPackageDetails.version;
225     this.vnfdInfo.id = vnfdPackageDetails.id;
226     this.vnfdInfo.provider = vnfdPackageDetails.provider;
227   }
228   /** Events handles at drag on D3 region @public */
229   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
230   public drag(ev: any): void {
231     ev.dataTransfer.setData('text', ev.target.id);
232   }
233   /** Events handles drop at D3 region @public */
234   public drop(ev: DragEvent): void {
235     ev.preventDefault();
236     const getDropedName: string = ev.dataTransfer.getData('text');
237     if (getDropedName === 'vdu') {
238       this.svg.selectAll('*').remove();
239       this.vduDropCompose();
240     } else if (getDropedName === 'cp') {
241       this.svg.selectAll('*').remove();
242       this.cpDropCompose();
243     } else if (getDropedName === 'intvl') {
244       this.svg.selectAll('*').remove();
245       this.intvlDropCompose();
246     }
247   }
248   /** Events handles allow drop on D3 region @public */
249   public allowDrop(ev: DragEvent): void {
250     ev.preventDefault();
251   }
252   /** Generate and list VDU @public */
253   public generateVDU(vnfdPackageDetails: VNFD): void {
254     if (vnfdPackageDetails.vdu !== undefined) {
255       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
256         this.nodes.push({
257           id: vdu.id,
258           name: vdu.name,
259           reflexive: false,
260           type: 'vdu'
261         });
262       });
263     }
264   }
265   /** Generate and list CP points @public */
266   public generateCPPoint(vnfdPackageDetails: VNFD): void {
267     if (vnfdPackageDetails['ext-cpd'] !== undefined) {
268       vnfdPackageDetails['ext-cpd'].forEach((cp: EXTCPD): void => {
269         this.nodes.push({
270           id: cp['int-cpd'].cpd !== undefined ? cp['int-cpd'].cpd : cp.id,
271           name: cp.id,
272           reflexive: false,
273           type: 'cp'
274         });
275       });
276     }
277   }
278   /** Generate and list Internal VLD @public */
279   public generateInternalVLD(vnfdPackageDetails: VNFD): void {
280     if (vnfdPackageDetails['int-virtual-link-desc'] !== undefined) {
281       vnfdPackageDetails['int-virtual-link-desc'].forEach((ivld: IVLD): void => {
282         this.nodes.push({
283           id: ivld.id,
284           name: ivld.id,
285           reflexive: false,
286           type: 'intvl'
287         });
288       });
289     }
290   }
291   /** Generate and list Internal CP @public */
292   public generateInternalCP(vnfdPackageDetails: VNFD): void {
293     if (vnfdPackageDetails.vdu !== undefined) {
294       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
295         if (vdu['int-cpd'] !== undefined) {
296           vdu['int-cpd'].forEach((intcpd: VDUINTCPD): void => {
297             if (intcpd['int-virtual-link-desc'] !== undefined) {
298               intcpd['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
299                 this.nodes.push({
300                   id: intcpd.id,
301                   name: vnir.name,
302                   reflexive: false,
303                   type: 'intcp'
304                 });
305               });
306             }
307           });
308         }
309       });
310     }
311   }
312   /** Generate VDU External and Internal CP Links @public */
313   public generateVDUCPLinks(vnfdPackageDetails: VNFD): void {
314     if (vnfdPackageDetails.vdu !== undefined) {
315       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
316         const vduLink: string = vdu.id;
317         if (vdu['int-cpd'] !== undefined) {
318           vdu['int-cpd'].forEach((intCPD: VDUINTCPD): void => {
319             if (intCPD['int-virtual-link-desc'] !== undefined) {
320               intCPD['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
321                 this.links.push({ source: vduLink, target: intCPD.id });
322               });
323             } else {
324               this.links.push({ source: vduLink, target: intCPD.id });
325             }
326           });
327         }
328       });
329     }
330   }
331   /** Generate Network/VLD/Internal VirtualLink, CP Links @public */
332   public generateIntVLCPLinks(vnfdPackageDetails: VNFD): void {
333     if (vnfdPackageDetails.vdu !== undefined) {
334       vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
335         if (vdu['int-cpd'] !== undefined) {
336           vdu['int-cpd'].forEach((intCPD: VDUINTCPD): void => {
337             const vldName: string = intCPD['int-virtual-link-desc'];
338             if (intCPD['int-virtual-link-desc'] !== undefined) {
339               intCPD['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
340                 this.links.push({ source: vldName, target: intCPD.id });
341               });
342             }
343           });
344         }
345       });
346     }
347   }
348   /** VNFD details can be saved on users inputs @public */
349   public saveVNFD(): void {
350     this.vnfdPackageDetails['product-name'] = this.vnfdInfo['product-name'];
351     this.vnfdPackageDetails.description = this.vnfdInfo.description;
352     this.vnfdPackageDetails.version = this.vnfdInfo.version;
353     this.vnfdPackageDetails.id = this.vnfdInfo.id;
354     this.vnfdPackageDetails.provider = this.vnfdInfo.provider;
355     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
356   }
357   /** VDU details can be saved on users inputs @public */
358   public saveVDU(getVDUID: string): void {
359     const getOLDVDUID: string = this.oldVDUID;
360     this.vnfdPackageDetails.vdu.forEach((ref: VDU): void => {
361       if (ref.id === getVDUID) {
362         ref.id = this.vduInfo.id;
363         ref.name = this.vduInfo.name;
364         ref.description = this.vduInfo.description !== undefined ? this.vduInfo.description : '';
365         ref['sw-image-desc'] = this.vduInfo['sw-image-desc'];
366       }
367     });
368     this.vnfdPackageDetails['ext-cpd'].forEach((extCPD: EXTCPD): void => {
369       if (extCPD['int-cpd'] !== undefined) {
370         if (extCPD['int-cpd']['vdu-id'] === getOLDVDUID) {
371           extCPD['int-cpd']['vdu-id'] = this.vduInfo.id;
372         }
373       }
374     });
375     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
376   }
377   /** IntVL details can be saved on users inputs @public */
378   public saveIntVL(intVLID: string): void {
379     const getOldID: string = this.oldintVLID;
380     this.vnfdPackageDetails['int-virtual-link-desc'].forEach((ivldDetails: IVLD): void => {
381       if (ivldDetails.id === intVLID) {
382         ivldDetails.id = this.intvlInfo.id;
383       }
384     });
385     this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU): void => {
386       if (vduDetails['int-cpd'] !== undefined) {
387         vduDetails['int-cpd'].forEach((intCPDDetails: VDUINTCPD): void => {
388           if (intCPDDetails['int-virtual-link-desc'] !== undefined) {
389             if (intCPDDetails['int-virtual-link-desc'] === getOldID) {
390               intCPDDetails['int-virtual-link-desc'] = this.intvlInfo.id;
391             }
392           }
393         });
394       }
395     });
396     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
397   }
398   /** IntVL details can be saved on users inputs @public */
399   public saveCP(cpID: string): void {
400     const getOldCP: string = this.oldCPID;
401     this.vnfdPackageDetails['ext-cpd'].forEach((ref: EXTCPD): void => {
402       if (ref.id === cpID) {
403         ref.id = this.cpInfo.id;
404       }
405     });
406     if (this.vnfdPackageDetails['mgmt-cp'] === getOldCP) {
407       this.vnfdPackageDetails['mgmt-cp'] = this.cpInfo.id;
408     }
409     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
410   }
411   /** Edit topology @public */
412   public onEdit(): void {
413     this.router.navigate(['/packages/vnf/edit/', this.identifier]).catch((): void => {
414       // Catch Navigation Error
415   });
416   }
417   /** Show Info @public */
418   public showInfo(): void {
419     // eslint-disable-next-line security/detect-non-literal-fs-filename
420     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
421     modalRef.componentInstance.topologyType = 'Info';
422     modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
423     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
424       if (result) {
425         // empty
426       }
427     }).catch((): void => {
428       // Catch Navigation Error
429   });
430   }
431   /** Event to freeze the animation @public */
432   public onFreeze(): void {
433     this.classApplied = !this.classApplied;
434     const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
435     d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
436     if (alreadyFixedIsActive) {
437       this.force.stop();
438     }
439     this.forceSimulationActive = alreadyFixedIsActive;
440     this.nodes.forEach((d: COMPOSERNODES): void => {
441       d.fx = (alreadyFixedIsActive) ? null : d.x;
442       d.fy = (alreadyFixedIsActive) ? null : d.y;
443     });
444     if (alreadyFixedIsActive) {
445       this.force.restart();
446     }
447   }
448   /** Events handles when dragended @public */
449   public toggleSidebar(): void {
450     this.sideBarOpened = !this.sideBarOpened;
451     this.deselectAllNodes();
452     this.showRightSideInfo = 'vnfdInfo';
453   }
454   /** Get the default Configuration of containers @private */
455   private getGraphContainerAttr(): GRAPHDETAILS {
456     return {
457       width: 700,
458       height: 400,
459       nodeHeight: 50,
460       nodeWidth: 35,
461       textX: -35,
462       textY: 30,
463       radius: 5,
464       distance: 50,
465       strength: -500,
466       forcex: 2,
467       forcey: 2,
468       sourcePaddingYes: 17,
469       sourcePaddingNo: 12,
470       targetPaddingYes: 4,
471       targetPaddingNo: 3,
472       alphaTarget: 0.3,
473       imageX: -25,
474       imageY: -25,
475       shiftKeyCode: 17
476     };
477   }
478   /** Node is created and render at D3 region @private */
479   private createNode(nodes: VNFD[]): void {
480     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
481     d3.selectAll('svg#graphContainer > *').remove();
482     d3.select(window).on('keydown', (): void => { this.keyDown(); });
483     d3.select(window).on('keyup', (): void => { this.keyUp(); });
484     this.svg = d3.select('#graphContainer')
485       .attr('oncontextmenu', 'return false;')
486       .attr('viewBox', `0 0 ${graphContainerAttr.width} ${graphContainerAttr.height}`)
487       .on('mousemove', (): void => { this.mousemove(); });
488     this.force = d3.forceSimulation()
489       .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance))
490       .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
491       .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
492       .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
493       .on('tick', (): void => { this.tick(); });
494     this.path = this.svg.append('svg:g').selectAll('path');
495     this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
496     this.network = this.svg.append('svg:g').selectAll('network');
497     this.virutualDeploymentUnit = this.svg.append('svg:g').selectAll('virutualDeploymentUnit');
498     this.connectionPoint = this.svg.append('svg:g').selectAll('connectionPoint');
499     this.intConnectionPoint = this.svg.append('svg:g').selectAll('intConnectionPoint');
500     this.restart(nodes);
501   }
502   /** Update force layout (called automatically each iteration) @private */
503   private tick(): void {
504     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
505     this.path.attr('d', (d: Tick): string => {
506       const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y;
507       const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
508       const normX: number = deltaX / dist; const normY: number = deltaY / dist;
509       const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
510       const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
511       const sourceX: number = d.source.x + (sourcePadding * normX); const sourceY: number = d.source.y + (sourcePadding * normY);
512       const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY);
513       return `M${sourceX},${sourceY}L${targetX},${targetY}`;
514     }).on('dblclick', (d: Tick): void => { this.getDeleteLinkConfirmation(d); });
515     this.network.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
516     this.virutualDeploymentUnit.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
517     this.connectionPoint.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
518     this.intConnectionPoint.attr('transform', (d: TickPath): string => `translate(${d.x},${d.y})`);
519   }
520   /** Update graph (called when needed) @private */
521   private restart(nodes: VNFD[]): void {
522     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
523     this.path = this.path.data(this.links);
524     const cpNodes: {}[] = []; const vduNodes: {}[] = []; const vlNodes: {}[] = []; const intcpNodes: {}[] = []; //Nodes are known by id
525     nodes.forEach((nodeList: COMPOSERNODES): void => {
526       if (nodeList.type === 'cp') { cpNodes.push(nodeList); }
527       else if (nodeList.type === 'vdu') { vduNodes.push(nodeList); }
528       else if (nodeList.type === 'intvl') { vlNodes.push(nodeList); }
529       else if (nodeList.type === 'intcp') { intcpNodes.push(nodeList); }
530     });
531     this.network = this.network.data(vlNodes, (d: VNFD): string => d.id);
532     this.virutualDeploymentUnit = this.virutualDeploymentUnit.data(vduNodes, (d: VNFD): string => d.id);
533     this.connectionPoint = this.connectionPoint.data(cpNodes, (d: VNFD): string => d.id);
534     this.intConnectionPoint = this.intConnectionPoint.data(intcpNodes, (d: VNFD): string => d.id);
535     this.resetAndCreateNodes();
536     this.force.nodes(nodes).force('link').links(this.links); //Set the graph in motion
537     this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
538   }
539   /** Rest and create nodes @private */
540   private resetAndCreateNodes(): void {
541     this.path.exit().remove();
542     this.network.exit().remove();
543     this.virutualDeploymentUnit.exit().remove();
544     this.connectionPoint.exit().remove();
545     this.intConnectionPoint.exit().remove();
546     this.getPathNodes();
547     this.getgNetwork();
548     this.getgVirutualDeploymentUnit();
549     this.getgConnectionPoint();
550     this.getgIntConnectionPoint();
551     this.network = this.gNetwork.merge(this.network);
552     this.virutualDeploymentUnit = this.gVirutualDeploymentUnit.merge(this.virutualDeploymentUnit);
553     this.connectionPoint = this.gConnectionPoint.merge(this.connectionPoint);
554     this.intConnectionPoint = this.gIntConnectionPoint.merge(this.intConnectionPoint);
555     this.path.merge(this.path);
556   }
557   /** Setting the Path @private */
558   private getPathNodes(): void {
559     this.path = this.path.enter().append('svg:path').attr('class', 'link');
560   }
561   /** Settings all the network attributes of nodes @private */
562   private getgNetwork(): void {
563     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
564     this.gNetwork = this.network.enter().append('svg:g');
565     this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
566     this.gNetwork.append('svg:image')
567       .style('opacity', 1)
568       .attr('x', graphContainerAttr.imageX)
569       .attr('y', graphContainerAttr.imageY)
570       .call(this.onDragDrop())
571       .attr('id', (d: COMPOSERNODES): string => d.id)
572       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
573       .attr('xlink:href', 'assets/images/INTVL.svg')
574       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
575       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
576       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.network, d); this.onNodeClickToggleSidebar(); })
577       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
578     this.gNetwork.append('svg:text')
579       .attr('class', 'node_text')
580       .attr('y', graphContainerAttr.textY)
581       .text((d: COMPOSERNODES): string => d.id);
582   }
583   /** Settings all the connection point attributes of nodes @private */
584   private getgVirutualDeploymentUnit(): void {
585     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
586     this.gVirutualDeploymentUnit = this.virutualDeploymentUnit.enter().append('svg:g');
587     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
588     this.gVirutualDeploymentUnit.append('svg:image')
589       .style('opacity', 1)
590       .attr('x', graphContainerAttr.imageX)
591       .attr('y', graphContainerAttr.imageY)
592       .call(this.onDragDrop())
593       .attr('id', (d: COMPOSERNODES): string => d.id)
594       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
595       .attr('xlink:href', 'assets/images/VDU.svg')
596       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
597       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
598       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.virutualDeploymentUnit, d); this.onNodeClickToggleSidebar(); })
599       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
600     this.gVirutualDeploymentUnit.append('svg:text')
601       .attr('class', 'node_text')
602       .attr('y', graphContainerAttr.textY)
603       .text((d: COMPOSERNODES): string => d.id);
604   }
605   /** Settings all the connection point attributes of nodes @private */
606   private getgConnectionPoint(): void {
607     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
608     this.gConnectionPoint = this.connectionPoint.enter().append('svg:g');
609     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
610     this.gConnectionPoint.append('svg:image')
611       .style('opacity', 1)
612       .attr('x', graphContainerAttr.imageX)
613       .attr('y', graphContainerAttr.imageY)
614       .call(this.onDragDrop())
615       .attr('id', (d: COMPOSERNODES): string => d.id)
616       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
617       .attr('xlink:href', 'assets/images/CP-VNF.svg')
618       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
619       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
620       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.connectionPoint, d); this.onNodeClickToggleSidebar(); })
621       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
622     this.gConnectionPoint.append('svg:text')
623       .attr('class', 'node_text')
624       .attr('y', graphContainerAttr.textY)
625       .text((d: COMPOSERNODES): string => d.name);
626   }
627   /** Settings all the internal connection point attributes of nodes @private */
628   private getgIntConnectionPoint(): void {
629     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
630     this.gIntConnectionPoint = this.intConnectionPoint.enter().append('svg:g');
631     this.gIntConnectionPoint.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
632     this.gIntConnectionPoint.append('svg:image')
633       .style('opacity', 1)
634       .attr('x', graphContainerAttr.imageX)
635       .attr('y', graphContainerAttr.imageY)
636       .call(this.onDragDrop())
637       .attr('id', (d: COMPOSERNODES): string => d.id)
638       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
639       .attr('xlink:href', 'assets/images/INTCP.svg')
640       .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
641       .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
642       .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.intConnectionPoint, d); this.onNodeClickToggleSidebar(); })
643       .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
644     this.gIntConnectionPoint.append('svg:text')
645       .attr('class', 'node_text')
646       .attr('y', graphContainerAttr.textY)
647       .text((d: COMPOSERNODES): string => d.name);
648   }
649   /** Drop VDU Composer Data @private */
650   private vduDropCompose(): void {
651     const randomID: string = this.sharedService.randomString();
652     if (this.vnfdPackageDetails['mgmt-cp'] === undefined) {
653       this.notifierService.notify('error', this.translateService.instant('PAGE.TOPOLOGY.ADDCPBEFOREVDU'));
654     } else {
655       if (this.vnfdPackageDetails.vdu === undefined) {
656         this.vnfdPackageDetails.vdu = [];
657       }
658       this.vnfdPackageDetails.vdu.push({
659         id: 'vdu_' + randomID,
660         name: 'vdu_' + randomID,
661         description: '',
662         'sw-image-desc': 'ubuntu',
663         'int-cpd': [],
664         'monitoring-parameter': [],
665         'virtual-compute-desc': '',
666         'virtual-storage-desc': []
667       });
668       this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
669     }
670   }
671   /** Drop CP Composer Data @private */
672   private cpDropCompose(): void {
673     const randomID: string = this.sharedService.randomString();
674     if (this.vnfdPackageDetails['ext-cpd'] === undefined) {
675       this.vnfdPackageDetails['ext-cpd'] = [];
676     }
677     this.vnfdPackageDetails['ext-cpd'].push({
678       id: 'cp_' + randomID,
679       'int-cpd': {}
680     });
681     if (this.vnfdPackageDetails['mgmt-cp'] === undefined) {
682       this.vnfdPackageDetails['mgmt-cp'] = 'cp_' + randomID;
683     }
684     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
685   }
686   /** Drop IntVL Composer Data @private */
687   private intvlDropCompose(): void {
688     const randomID: string = this.sharedService.randomString();
689     if (this.vnfdPackageDetails['int-virtual-link-desc'] === undefined) {
690       this.vnfdPackageDetails['int-virtual-link-desc'] = [];
691     }
692     this.vnfdPackageDetails['int-virtual-link-desc'].push({
693       id: 'vnf_vl_' + randomID
694     });
695     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
696   }
697   /** Add the Add Nodes Data @private */
698   private addNodes(apiURL: string, identifier: string, data: VNFD): void {
699     this.isLoadingResults = true;
700     const apiURLHeader: APIURLHEADER = {
701       url: apiURL + '/' + identifier + '/package_content',
702       httpOptions: { headers: this.headers }
703     };
704     const vnfData: VNFDATA = {};
705     vnfData.vnfd = data;
706     const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
707     this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
708       .then((content: ArrayBuffer): void => {
709         this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => {
710           this.generateData();
711           this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
712           this.isLoadingResults = false;
713         }, (error: ERRORDATA): void => {
714           this.generateData();
715           this.restService.handleError(error, 'put');
716           this.isLoadingResults = false;
717         });
718       }).catch((): void => {
719         this.notifierService.notify('error', this.translateService.instant('ERROR'));
720         this.isLoadingResults = false;
721       });
722   }
723   /** Events handles when mousedown click it will capture the selected node data @private */
724   private mouseDown(d: COMPOSERNODES): void {
725     // eslint-disable-next-line deprecation/deprecation
726     event.preventDefault();
727     if (d3.event.ctrlKey) { return; }
728     if (d3.event.shiftKey) {
729       this.mousedownNode = d;
730       this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
731       this.dragLine.classed('hidden', false)
732         .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
733     }
734   }
735   /** Event handles when mouseup event occures @private */
736   private mouseUp(d: COMPOSERNODES): void {
737     if (!this.mousedownNode) { return; }
738     this.dragLine.classed('hidden', true);
739     this.mouseupNode = d;
740     if (this.mousedownNode.type === 'vdu') {
741       this.vduMouseDownNode();
742     } else if (this.mousedownNode.type === 'cp') {
743       this.cpMouseDownNode();
744     } else if (this.mousedownNode.type === 'intvl') {
745       this.intVLMouseDownNode();
746     } else if (this.mousedownNode.type === 'intcp') {
747       this.intCPMouseDownNode();
748     } else {
749       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
750       this.deselectPath();
751     }
752     this.resetMouseActions();
753     this.currentSelectedNode = null;
754   }
755   /** Establish a connection point between vdu and other nodes @private */
756   private vduMouseDownNode(): void {
757     if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'cp') {
758       this.vduCPConnection(this.mousedownNode.id, this.mouseupNode.id);
759     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intcp') {
760       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
761       this.deselectPath();
762     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'vdu') {
763       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
764       this.deselectPath();
765     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intvl') {
766       this.vduIntvlConnection(this.mousedownNode.id, this.mouseupNode.id);
767     }
768   }
769   /** Establish a connection point between cp and other nodes @private */
770   private cpMouseDownNode(): void {
771     if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'vdu') {
772       this.vduCPConnection(this.mouseupNode.id, this.mousedownNode.id);
773     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intvl') {
774       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
775       this.deselectPath();
776     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intcp') {
777       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
778       this.deselectPath();
779     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'cp') {
780       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDCP'));
781       this.deselectPath();
782     }
783   }
784   /** Establish a connection piont between intvl and other nodes @private */
785   private intVLMouseDownNode(): void {
786     if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'cp') {
787       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
788       this.deselectPath();
789     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'vdu') {
790       this.vduIntvlConnection(this.mouseupNode.id, this.mousedownNode.id);
791     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intvl') {
792       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDVNFVL'));
793       this.deselectPath();
794     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intcp') {
795       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDONTCP'));
796       this.deselectPath();
797     }
798   }
799   /** Establish a connection point between intcp and other nodes @private */
800   private intCPMouseDownNode(): void {
801     if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'vdu') {
802       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
803       this.deselectPath();
804     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'cp') {
805       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
806       this.deselectPath();
807     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intvl') {
808       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVNFVL'));
809       this.deselectPath();
810     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intcp') {
811       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDINTCP'));
812       this.deselectPath();
813     }
814   }
815   /** Establish a connection between VDU & CP vice versa @private */
816   private vduCPConnection(nodeA: string, nodeB: string): void {
817     const vduExternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
818     if (this.vnfdPackageDetails.vdu !== undefined) {
819       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
820         const vduID: string = vdu.id;
821         if (vdu.id === nodeA) {
822           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
823             this.vnfdPackageDetails['ext-cpd'].forEach((extcpd: EXTCPD, index: number): void => {
824               if (extcpd.id === nodeB) {
825                 if (vdu['int-cpd'] === undefined) {
826                   vdu['int-cpd'] = [];
827                 }
828                 vdu['int-cpd'].push({
829                   id: vduExternalID,
830                   'virtual-network-interface-requirement': [
831                     {
832                       name: vduExternalID,
833                       position: 1,
834                       'virtual-interface': { type: 'PARAVIRT' }
835                     }
836                   ]
837                 });
838                 // eslint-disable-next-line security/detect-object-injection
839                 this.vnfdPackageDetails['ext-cpd'][index] = {
840                   id: extcpd.id,
841                   'int-cpd': {
842                     cpd: vduExternalID,
843                     'vdu-id': vduID
844                   }
845                 };
846               }
847             });
848           }
849         }
850       });
851     }
852     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
853     this.deselectPath();
854   }
855   /** Establish a connection between vdu & intvl and vice versa @private */
856   private vduIntvlConnection(nodeA: string, nodeB: string): void {
857     const vduInternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
858     if (this.vnfdPackageDetails.vdu !== undefined) {
859       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
860         if (vdu.id === nodeA) {
861           if (vdu['int-cpd'] === undefined) {
862             vdu['int-cpd'] = [];
863           }
864           vdu['int-cpd'].push({
865             id: vduInternalID,
866             'int-virtual-link-desc': nodeB,
867             'virtual-network-interface-requirement': [
868               {
869                 name: vduInternalID,
870                 position: 1,
871                 'virtual-interface': { type: 'PARAVIRT' }
872               }
873             ]
874           });
875         }
876       });
877     }
878     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
879     this.deselectPath();
880   }
881   /** Events handles when mousemove it will capture the selected node data @private */
882   private mousemove(): void {
883     if (!this.mousedownNode) { return; }
884     this.dragLine.attr('d',
885       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
886   }
887   /** reset Mouse varaibles @private */
888   private resetMouseActions(): void {
889     this.mousedownNode = null;
890     this.mouseupNode = null;
891   }
892   /** drag event @private */
893   // eslint-disable-next-line @typescript-eslint/no-explicit-any
894   private onDragDrop(): any {
895     return d3.drag().filter(this.dragFilter)
896       .on('start', this.dragstarted)
897       .on('drag', this.dragged)
898       .on('end', this.dragended);
899   }
900   /** Key press event @private */
901   private keyDown(): void {
902     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
903     if (this.lastKeyDown !== -1) { return; }
904     this.lastKeyDown = d3.event.keyCode;
905     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
906       this.svg.classed('ctrl', true);
907     }
908   }
909   /** Key realse event @private */
910   private keyUp(): void {
911     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
912     this.lastKeyDown = -1;
913     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
914       this.gNetwork.on('.drag', null);
915       this.gVirutualDeploymentUnit.on('.drag', null);
916       this.gConnectionPoint.on('.drag', null);
917       this.gIntConnectionPoint.on('.drag', null);
918       this.svg.classed('ctrl', false);
919     }
920   }
921   /** Mosue Drag Line false if it is not satisfied @private */
922   private deselectPath(): void {
923     this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
924   }
925   /** Events handles when Shift Click to perform create cp @private */
926   // eslint-disable-next-line @typescript-eslint/no-explicit-any
927   private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
928     this.selectedNode(nodeSelected, d);
929   }
930   /** Get confirmation Before Deleting the Node in Topology @private */
931   private getDeleteNodeConfirmation(d: COMPOSERNODES): void {
932     // eslint-disable-next-line security/detect-non-literal-fs-filename
933     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
934     modalRef.componentInstance.topologyType = 'Delete';
935     modalRef.componentInstance.topologyname = d.name;
936     if (d.type === 'vdu') {
937       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
938     } else if (d.type === 'intvl') {
939       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
940     } else if (d.type === 'cp') {
941       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
942     } else if (d.type === 'intcp') {
943       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
944     }
945     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
946       if (result) {
947         this.deleteNode(d);
948       }
949     }).catch((): void => {
950       // Catch Navigation Error
951   });
952   }
953   /** Delete nodes @private */
954   private deleteNode(d: COMPOSERNODES): void {
955     this.nodes.forEach((node: VNFD): void => {
956       if (node.id === d.id) {
957         if (d.type === 'cp') {
958           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
959             let getRelatedVDUCPD: string; let getRelatedVDUID: string;
960             const posExtCPD: number = this.vnfdPackageDetails['ext-cpd'].findIndex((e: EXTCPD): boolean => {
961               if (e.id === d.name) {
962                 if (e['int-cpd'] !== undefined) {
963                   getRelatedVDUCPD = e['int-cpd'].cpd; getRelatedVDUID = e['int-cpd']['vdu-id'];
964                 }
965                 return true;
966               } else {
967                 return false;
968               }
969             });
970             if (posExtCPD !== -1) {
971               this.vnfdPackageDetails['ext-cpd'].splice(posExtCPD, 1);
972             }
973             if (getRelatedVDUCPD !== undefined && getRelatedVDUID !== undefined) {
974               this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
975                 if (vdu.id === getRelatedVDUID) {
976                   const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => intCPD.id === getRelatedVDUCPD);
977                   if (posINTCPD !== -1) {
978                     vdu['int-cpd'].splice(posINTCPD, 1);
979                   }
980                 }
981               });
982             }
983           }
984         } else if (d.type === 'intcp') {
985           this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
986             const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => intCPD.id === d.id);
987             if (posINTCPD !== -1) {
988               vdu['int-cpd'].splice(posINTCPD, 1);
989             }
990           });
991         } else if (d.type === 'intvl') {
992           const posINTVLD: number = this.vnfdPackageDetails['int-virtual-link-desc'].findIndex((intVLD: IVLD): boolean => intVLD.id === d.id);
993           if (posINTVLD !== -1) {
994             this.vnfdPackageDetails['int-virtual-link-desc'].splice(posINTVLD, 1);
995           }
996           if (this.vnfdPackageDetails.vdu !== undefined) {
997             this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU): void => {
998               if (vduDetails['int-cpd'] !== undefined) {
999                 const newVDUintCPDArray: VDUINTCPD[] = vduDetails['int-cpd'].filter((item: VDUINTCPD): boolean => item['int-virtual-link-desc'] !== undefined ? item['int-virtual-link-desc'] !== d.id ? true : false : true);
1000                 vduDetails['int-cpd'] = newVDUintCPDArray;
1001               }
1002             });
1003           }
1004         } else if (d.type === 'vdu') {
1005           const getRelatedExtCPD: string[] = [];
1006           const posVDU: number = this.vnfdPackageDetails.vdu.findIndex((vduDetails: VDU): boolean => {
1007             if (vduDetails.id === d.id) {
1008               if (vduDetails['int-cpd'] !== undefined) {
1009                 vduDetails['int-cpd'].forEach((intCPDDetails: VDUINTCPD): void => {
1010                   if (intCPDDetails['int-virtual-link-desc'] === undefined) {
1011                     getRelatedExtCPD.push(intCPDDetails.id);
1012                   }
1013                 });
1014               }
1015               return true;
1016             } else {
1017               return false;
1018             }
1019           });
1020           if (posVDU !== -1) {
1021             this.vnfdPackageDetails.vdu.splice(posVDU, 1);
1022           }
1023           getRelatedExtCPD.forEach((CPDID: string, index: number): void => {
1024             this.vnfdPackageDetails['ext-cpd'].forEach((extCPD: EXTCPD): void => {
1025               if (extCPD['int-cpd'] !== undefined) {
1026                 if (extCPD['int-cpd'].cpd === CPDID) {
1027                   extCPD['int-cpd'] = {};
1028                 }
1029               }
1030             });
1031           });
1032         } else {
1033           this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
1034         }
1035         this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
1036       }
1037     });
1038   }
1039   /** Get confirmation before deleting the ink in Topology @private */
1040   private getDeleteLinkConfirmation(d: Tick): void {
1041     this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
1042   }
1043   /** Selected nodes @private */
1044   // eslint-disable-next-line @typescript-eslint/no-explicit-any
1045   private selectedNode(nodeSeleced: any, d: COMPOSERNODES): void {
1046     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
1047     this.deselectAllNodes();
1048     nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
1049     if (d.type === 'vdu' && !alreadyIsActive) {
1050       this.vnfdPackageDetails.vdu.forEach((res: VDU): void => {
1051         if (res.id === d.id) {
1052           this.showRightSideInfo = 'vduInfo';
1053           this.vduInfo = res;
1054           this.oldVDUID = res.id;
1055         }
1056       });
1057     } else if (d.type === 'cp' && !alreadyIsActive) {
1058       this.vnfdPackageDetails['ext-cpd'].forEach((cp: EXTCPD): void => {
1059         const getCPDID: string = cp['int-cpd'] !== undefined ? cp['int-cpd'].cpd : cp.id;
1060         if (getCPDID === d.id) {
1061           this.showRightSideInfo = 'cpInfo';
1062           this.cpInfo = cp;
1063           this.oldCPID = cp.id;
1064         }
1065       });
1066     } else if (d.type === 'intvl' && !alreadyIsActive) {
1067       this.vnfdPackageDetails['int-virtual-link-desc'].forEach((ivld: IVLD): void => {
1068         if (ivld.id === d.id) {
1069           this.showRightSideInfo = 'intvlInfo';
1070           this.intvlInfo = ivld;
1071           this.oldintVLID = ivld.id;
1072         }
1073       });
1074     } else if (d.type === 'intcp' && !alreadyIsActive) {
1075       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
1076         vdu['int-cpd'].forEach((intcpd: VDUINTCPD): void => {
1077           if (intcpd.id === d.id) {
1078             if (intcpd['int-virtual-link-desc'] !== undefined) {
1079               intcpd['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
1080                 this.intcpInfo = vnir;
1081                 this.showRightSideInfo = 'intcpInfo';
1082               });
1083             }
1084           }
1085         });
1086       });
1087     } else {
1088       this.showRightSideInfo = 'vnfdInfo';
1089     }
1090   }
1091   /** De-select all the selected nodes @private */
1092   private deselectAllNodes(): void {
1093     this.network.select('image').classed(this.activeNode, false);
1094     this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
1095     this.connectionPoint.select('image').classed(this.activeNode, false);
1096     this.intConnectionPoint.select('image').classed(this.activeNode, false);
1097   }
1098   /** Events handles when to drag using filter for the keys @private */
1099   private dragFilter(): boolean {
1100     return d3.event.ctrlKey && !d3.event.button;
1101   }
1102   /** Events handles when dragstarted @private */
1103   private dragstarted(d: COMPOSERNODES): void {
1104     d.fx = d.x;
1105     d.fy = d.y;
1106   }
1107   /** Events handles when dragged @private */
1108   private dragged(d: COMPOSERNODES): void {
1109     d.fx = d.x = d3.event.x;
1110     d.fy = d.y = d3.event.y;
1111   }
1112   /** Events handles when dragended @private */
1113   private dragended(d: COMPOSERNODES): void {
1114     if (this.forceSimulationActive) {
1115       d.fx = null;
1116       d.fy = null;
1117     } else {
1118       d.fx = d.x;
1119       d.fy = d.y;
1120       this.forceSimulationActive = false;
1121     }
1122   }
1123   /** Events handles when node double click   @private */
1124   private onNodedblClickToggleSidebar(): void {
1125     this.sideBarOpened = false;
1126   }
1127   /** Events handles when node single click   @private */
1128   private onNodeClickToggleSidebar(): void {
1129     this.sideBarOpened = true;
1130   }
1131 }