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