Bug 1383 Error when consulting NS instance's topology
[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'] !== 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.vdu === undefined) {
647       this.vnfdPackageDetails.vdu = [];
648     }
649     this.vnfdPackageDetails.vdu.push({
650       id: 'vdu_' + randomID,
651       name: 'vdu_' + randomID,
652       description: '',
653       'sw-image-desc': 'ubuntu',
654       'int-cpd': [],
655       'monitoring-parameter': [],
656       'virtual-compute-desc': '',
657       'virtual-storage-desc': []
658     });
659     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
660   }
661   /** Drop CP Composer Data @private */
662   private cpDropCompose(): void {
663     const randomID: string = this.sharedService.randomString();
664     if (this.vnfdPackageDetails['ext-cpd'] === undefined) {
665       this.vnfdPackageDetails['ext-cpd'] = [];
666       this.vnfdPackageDetails['mgmt-cp'] = 'cp_' + randomID;
667     }
668     this.vnfdPackageDetails['ext-cpd'].push({
669       id: 'cp_' + randomID,
670       'int-cpd': {}
671     });
672     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
673   }
674   /** Drop IntVL Composer Data @private */
675   private intvlDropCompose(): void {
676     const randomID: string = this.sharedService.randomString();
677     if (this.vnfdPackageDetails['int-virtual-link-desc'] === undefined) {
678       this.vnfdPackageDetails['int-virtual-link-desc'] = [];
679     }
680     this.vnfdPackageDetails['int-virtual-link-desc'].push({
681       id: 'vnf_vl_' + randomID
682     });
683     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
684   }
685   /** Add the Add Nodes Data @private */
686   private addNodes(apiURL: string, identifier: string, data: VNFD): void {
687     this.isLoadingResults = true;
688     const apiURLHeader: APIURLHEADER = {
689       url: apiURL + '/' + identifier + '/package_content',
690       httpOptions: { headers: this.headers }
691     };
692     const vnfData: VNFDATA = {};
693     vnfData.vnfd = data;
694     const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
695     this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
696       .then((content: ArrayBuffer): void => {
697         this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => {
698           this.generateData();
699           this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
700           this.isLoadingResults = false;
701         }, (error: ERRORDATA): void => {
702           this.generateData();
703           this.restService.handleError(error, 'put');
704           this.isLoadingResults = false;
705         });
706       }).catch((): void => {
707         this.notifierService.notify('error', this.translateService.instant('ERROR'));
708         this.isLoadingResults = false;
709       });
710   }
711   /** Events handles when mousedown click it will capture the selected node data @private */
712   private mouseDown(d: COMPOSERNODES): void {
713     event.preventDefault();
714     if (d3.event.ctrlKey) { return; }
715     if (d3.event.shiftKey) {
716       this.mousedownNode = d;
717       this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
718       this.dragLine.classed('hidden', false)
719         .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
720     }
721   }
722   /** Event handles when mouseup event occures @private */
723   private mouseUp(d: COMPOSERNODES): void {
724     if (!this.mousedownNode) { return; }
725     this.dragLine.classed('hidden', true);
726     this.mouseupNode = d;
727     if (this.mousedownNode.type === 'vdu') {
728       this.vduMouseDownNode();
729     } else if (this.mousedownNode.type === 'cp') {
730       this.cpMouseDownNode();
731     } else if (this.mousedownNode.type === 'intvl') {
732       this.intVLMouseDownNode();
733     } else if (this.mousedownNode.type === 'intcp') {
734       this.intCPMouseDownNode();
735     } else {
736       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
737       this.deselectPath();
738     }
739     this.resetMouseActions();
740     this.currentSelectedNode = null;
741   }
742   /** Establish a connection point between vdu and other nodes @private */
743   private vduMouseDownNode(): void {
744     if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'cp') {
745       this.vduCPConnection(this.mousedownNode.id, this.mouseupNode.id);
746     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intcp') {
747       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
748       this.deselectPath();
749     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'vdu') {
750       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
751       this.deselectPath();
752     } else if (this.mousedownNode.type === 'vdu' && this.mouseupNode.type === 'intvl') {
753       this.vduIntvlConnection(this.mousedownNode.id, this.mouseupNode.id);
754     }
755   }
756   /** Establish a connection point between cp and other nodes @private */
757   private cpMouseDownNode(): void {
758     if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'vdu') {
759       this.vduCPConnection(this.mouseupNode.id, this.mousedownNode.id);
760     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intvl') {
761       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
762       this.deselectPath();
763     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'intcp') {
764       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
765       this.deselectPath();
766     } else if (this.mousedownNode.type === 'cp' && this.mouseupNode.type === 'cp') {
767       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDCP'));
768       this.deselectPath();
769     }
770   }
771   /** Establish a connection piont between intvl and other nodes @private */
772   private intVLMouseDownNode(): void {
773     if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'cp') {
774       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
775       this.deselectPath();
776     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'vdu') {
777       this.vduIntvlConnection(this.mouseupNode.id, this.mousedownNode.id);
778     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intvl') {
779       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDVNFVL'));
780       this.deselectPath();
781     } else if (this.mousedownNode.type === 'intvl' && this.mouseupNode.type === 'intcp') {
782       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDONTCP'));
783       this.deselectPath();
784     }
785   }
786   /** Establish a connection point between intcp and other nodes @private */
787   private intCPMouseDownNode(): void {
788     if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'vdu') {
789       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
790       this.deselectPath();
791     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'cp') {
792       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
793       this.deselectPath();
794     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intvl') {
795       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVNFVL'));
796       this.deselectPath();
797     } else if (this.mousedownNode.type === 'intcp' && this.mouseupNode.type === 'intcp') {
798       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDINTCP'));
799       this.deselectPath();
800     }
801   }
802   /** Establish a connection between VDU & CP vice versa @private */
803   private vduCPConnection(nodeA: string, nodeB: string): void {
804     const vduExternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
805     if (this.vnfdPackageDetails.vdu !== undefined) {
806       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
807         const vduID: string = vdu.id;
808         if (vdu.id === nodeA) {
809           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
810             this.vnfdPackageDetails['ext-cpd'].forEach((extcpd: EXTCPD, index: number): void => {
811               if (extcpd.id === nodeB) {
812                 if (vdu['int-cpd'] === undefined) {
813                   vdu['int-cpd'] = [];
814                 }
815                 if (extcpd['int-cpd'] === undefined) {
816                   vdu['int-cpd'].push({
817                     id: vduExternalID,
818                     'virtual-network-interface-requirement': [
819                       {
820                         name: vduExternalID,
821                         position: 1,
822                         'virtual-interface': { type: 'PARAVIRT' }
823                       }
824                     ]
825                   });
826                   this.vnfdPackageDetails['ext-cpd'][index] = {
827                     id: extcpd.id,
828                     'int-cpd': {
829                       cpd: vduExternalID,
830                       'vdu-id': vduID
831                     }
832                   };
833                 }
834               }
835             });
836           }
837         }
838       });
839     }
840     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
841     this.deselectPath();
842   }
843   /** Establish a connection between vdu & intvl and vice versa @private */
844   private vduIntvlConnection(nodeA: string, nodeB: string): void {
845     const vduInternalID: string = nodeA + '-eth_' + this.sharedService.randomString();
846     if (this.vnfdPackageDetails.vdu !== undefined) {
847       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
848         if (vdu.id === nodeA) {
849           if (vdu['int-cpd'] === undefined) {
850             vdu['int-cpd'] = [];
851           }
852           vdu['int-cpd'].push({
853             id: vduInternalID,
854             'int-virtual-link-desc': nodeB,
855             'virtual-network-interface-requirement': [
856               {
857                 name: vduInternalID,
858                 position: 1,
859                 'virtual-interface': { type: 'PARAVIRT' }
860               }
861             ]
862           });
863         }
864       });
865     }
866     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
867     this.deselectPath();
868   }
869   /** Events handles when mousemove it will capture the selected node data @private */
870   private mousemove(): void {
871     if (!this.mousedownNode) { return; }
872     this.dragLine.attr('d',
873       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
874   }
875   /** reset Mouse varaibles @private */
876   private resetMouseActions(): void {
877     this.mousedownNode = null;
878     this.mouseupNode = null;
879   }
880   /** drag event @private */
881   // tslint:disable-next-line: no-any
882   private onDragDrop(): any {
883     return d3.drag().filter(this.dragFilter)
884       .on('start', this.dragstarted)
885       .on('drag', this.dragged)
886       .on('end', this.dragended);
887   }
888   /** Key press event @private */
889   private keyDown(): void {
890     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
891     if (this.lastKeyDown !== -1) { return; }
892     this.lastKeyDown = d3.event.keyCode;
893     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
894       this.svg.classed('ctrl', true);
895     }
896   }
897   /** Key realse event @private */
898   private keyUp(): void {
899     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
900     this.lastKeyDown = -1;
901     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
902       this.gNetwork.on('.drag', null);
903       this.gVirutualDeploymentUnit.on('.drag', null);
904       this.gConnectionPoint.on('.drag', null);
905       this.gIntConnectionPoint.on('.drag', null);
906       this.svg.classed('ctrl', false);
907     }
908   }
909   /** Mosue Drag Line false if it is not satisfied @private */
910   private deselectPath(): void {
911     this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
912   }
913   /** Events handles when Shift Click to perform create cp @private */
914   // tslint:disable-next-line: no-any
915   private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
916     this.selectedNode(nodeSelected, d);
917   }
918   /** Get confirmation Before Deleting the Node in Topology @private */
919   private getDeleteNodeConfirmation(d: COMPOSERNODES): void {
920     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
921     modalRef.componentInstance.topologyType = 'Delete';
922     modalRef.componentInstance.topologyname = d.name;
923     if (d.type === 'vdu') {
924       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
925     } else if (d.type === 'intvl') {
926       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
927     } else if (d.type === 'cp') {
928       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
929     } else if (d.type === 'intcp') {
930       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
931     }
932     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
933       if (result) {
934         this.deleteNode(d);
935       }
936     }).catch();
937   }
938   /** Delete nodes @private */
939   private deleteNode(d: COMPOSERNODES): void {
940     // tslint:disable-next-line: max-func-body-length
941     this.nodes.forEach((node: VNFD): void => {
942       if (node.id === d.id) {
943         if (d.type === 'cp') {
944           if (this.vnfdPackageDetails['ext-cpd'] !== undefined) {
945             let getRelatedVDUCPD: string; let getRelatedVDUID: string;
946             const posExtCPD: number = this.vnfdPackageDetails['ext-cpd'].findIndex((e: EXTCPD): boolean => {
947               if (e.id === d.name) {
948                 if (e['int-cpd'] !== undefined) {
949                   getRelatedVDUCPD = e['int-cpd'].cpd; getRelatedVDUID = e['int-cpd']['vdu-id'];
950                 }
951                 return true;
952               } else {
953                 return false;
954               }
955             });
956             if (posExtCPD !== -1) {
957               this.vnfdPackageDetails['ext-cpd'].splice(posExtCPD, 1);
958             }
959             if (getRelatedVDUCPD !== undefined && getRelatedVDUID !== undefined) {
960               this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
961                 if (vdu.id === getRelatedVDUID) {
962                   const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => {
963                     return intCPD.id === getRelatedVDUCPD;
964                   });
965                   if (posINTCPD !== -1) {
966                     vdu['int-cpd'].splice(posINTCPD, 1);
967                   }
968                 }
969               });
970             }
971           }
972         } else if (d.type === 'intcp') {
973           this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
974             const posINTCPD: number = vdu['int-cpd'].findIndex((intCPD: VDUINTCPD): boolean => {
975               return intCPD.id === d.id;
976             });
977             if (posINTCPD !== -1) {
978               vdu['int-cpd'].splice(posINTCPD, 1);
979             }
980           });
981         } else if (d.type === 'intvl') {
982           const posINTVLD: number = this.vnfdPackageDetails['int-virtual-link-desc'].findIndex((intVLD: IVLD): boolean => {
983             return intVLD.id === d.id;
984           });
985           if (posINTVLD !== -1) {
986             this.vnfdPackageDetails['int-virtual-link-desc'].splice(posINTVLD, 1);
987           }
988           if (this.vnfdPackageDetails.vdu !== undefined) {
989             this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU): void => {
990               if (vduDetails['int-cpd'] !== undefined) {
991                 const newVDUintCPDArray: VDUINTCPD[] = vduDetails['int-cpd'].filter((item: VDUINTCPD): boolean => {
992                   return item['int-virtual-link-desc'] !== undefined ? item['int-virtual-link-desc'] !== d.id ? true : false : true;
993                 });
994                 vduDetails['int-cpd'] = newVDUintCPDArray;
995               }
996             });
997           }
998         } else if (d.type === 'vdu') {
999           const getRelatedExtCPD: string[] = [];
1000           const posVDU: number = this.vnfdPackageDetails.vdu.findIndex((vduDetails: VDU): boolean => {
1001             if (vduDetails.id === d.id) {
1002               if (vduDetails['int-cpd'] !== undefined) {
1003                 vduDetails['int-cpd'].forEach((intCPDDetails: VDUINTCPD): void => {
1004                   if (intCPDDetails['int-virtual-link-desc'] === undefined) {
1005                     getRelatedExtCPD.push(intCPDDetails.id);
1006                   }
1007                 });
1008               }
1009               return true;
1010             } else {
1011               return false;
1012             }
1013           });
1014           if (posVDU !== -1) {
1015             this.vnfdPackageDetails.vdu.splice(posVDU, 1);
1016           }
1017           getRelatedExtCPD.forEach((CPDID: string, index: number): void => {
1018             this.vnfdPackageDetails['ext-cpd'].forEach((extCPD: EXTCPD): void => {
1019               if (extCPD['int-cpd'] !== undefined) {
1020                 if (extCPD['int-cpd'].cpd === CPDID) {
1021                   delete extCPD['int-cpd'];
1022                 }
1023               }
1024             });
1025           });
1026         } else {
1027           this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
1028         }
1029         this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
1030       }
1031     });
1032   }
1033   /** Get confirmation before deleting the ink in Topology @private */
1034   private getDeleteLinkConfirmation(d: Tick): void {
1035     this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
1036   }
1037   /** Selected nodes @private */
1038   // tslint:disable-next-line: no-any
1039   private selectedNode(nodeSeleced: any, d: COMPOSERNODES): void {
1040     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
1041     this.deselectAllNodes();
1042     nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
1043     if (d.type === 'vdu' && !alreadyIsActive) {
1044       this.vnfdPackageDetails.vdu.forEach((res: VDU): void => {
1045         if (res.id === d.id) {
1046           this.showRightSideInfo = 'vduInfo';
1047           this.vduInfo = res;
1048           this.oldVDUID = res.id;
1049         }
1050       });
1051     } else if (d.type === 'cp' && !alreadyIsActive) {
1052       this.vnfdPackageDetails['ext-cpd'].forEach((cp: EXTCPD): void => {
1053         const getCPDID: string = cp['int-cpd'] !== undefined ? cp['int-cpd'].cpd : cp.id;
1054         if (getCPDID === d.id) {
1055           this.showRightSideInfo = 'cpInfo';
1056           this.cpInfo = cp;
1057           this.oldCPID = cp.id;
1058         }
1059       });
1060     } else if (d.type === 'intvl' && !alreadyIsActive) {
1061       this.vnfdPackageDetails['int-virtual-link-desc'].forEach((ivld: IVLD): void => {
1062         if (ivld.id === d.id) {
1063           this.showRightSideInfo = 'intvlInfo';
1064           this.intvlInfo = ivld;
1065           this.oldintVLID = ivld.id;
1066         }
1067       });
1068     } else if (d.type === 'intcp' && !alreadyIsActive) {
1069       this.vnfdPackageDetails.vdu.forEach((vdu: VDU): void => {
1070         vdu['int-cpd'].forEach((intcpd: VDUINTCPD): void => {
1071           if (intcpd.id === d.id) {
1072             if (intcpd['int-virtual-link-desc'] !== undefined) {
1073               intcpd['virtual-network-interface-requirement'].forEach((vnir: VNIR): void => {
1074                 this.intcpInfo = vnir;
1075                 this.showRightSideInfo = 'intcpInfo';
1076               });
1077             }
1078           }
1079         });
1080       });
1081     } else {
1082       this.showRightSideInfo = 'vnfdInfo';
1083     }
1084   }
1085   /** De-select all the selected nodes @private */
1086   private deselectAllNodes(): void {
1087     this.network.select('image').classed(this.activeNode, false);
1088     this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
1089     this.connectionPoint.select('image').classed(this.activeNode, false);
1090     this.intConnectionPoint.select('image').classed(this.activeNode, false);
1091   }
1092   /** Events handles when to drag using filter for the keys @private */
1093   private dragFilter(): boolean {
1094     return d3.event.ctrlKey && !d3.event.button;
1095   }
1096   /** Events handles when dragstarted @private */
1097   private dragstarted(d: COMPOSERNODES): void {
1098     d.fx = d.x;
1099     d.fy = d.y;
1100   }
1101   /** Events handles when dragged @private */
1102   private dragged(d: COMPOSERNODES): void {
1103     d.fx = d.x = d3.event.x;
1104     d.fy = d.y = d3.event.y;
1105   }
1106   /** Events handles when dragended @private */
1107   private dragended(d: COMPOSERNODES): void {
1108     if (this.forceSimulationActive) {
1109       d.fx = null;
1110       d.fy = null;
1111     } else {
1112       d.fx = d.x;
1113       d.fy = d.y;
1114       this.forceSimulationActive = false;
1115     }
1116   }
1117   /** Events handles when node double click   @private */
1118   private onNodedblClickToggleSidebar(): void {
1119     this.sideBarOpened = false;
1120   }
1121   /** Events handles when node single click   @private */
1122   private onNodeClickToggleSidebar(): void {
1123     this.sideBarOpened = true;
1124   }
1125 }