21aad711f977f6da47860f74acec63d5506d9784
[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, GETAPIURLHEADER, 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 { isNullOrUndefined } from 'util';
37 import {
38   COMPOSERNODES, CONNECTIONPOINT, GRAPHDETAILS, InternalVLD, Tick, TickPath,
39   VDU, VDUInternalConnectionPoint, VLDInternalConnectionPoint, VNFDInterface, VNFDNODE
40 } from 'VNFDModel';
41
42 /**
43  * Creating component
44  * @Component takes VNFComposerComponent.html as template url
45  */
46 @Component({
47   templateUrl: './VNFComposerComponent.html',
48   styleUrls: ['./VNFComposerComponent.scss'],
49   encapsulation: ViewEncapsulation.None
50 })
51 /** Exporting a class @exports VNFComposerComponent */
52 export class VNFComposerComponent {
53   /** To inject services @public */
54   public injector: Injector;
55   /** View child contains graphContainer ref @public  */
56   @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
57   /** dataService to pass the data from one component to another @public */
58   public dataService: DataService;
59   /** random number count @public */
60   public randomNumberLength: number;
61   /** Contains the vnfd information @public */
62   public vnfList: string[] = [];
63   /** Contains node type @public */
64   public nodeTypeRef: string;
65   /** Contains VNFD Information @public */
66   public vnfdInfo: VNFDNODE = { shortName: '', description: '', version: '', id: '', name: '' };
67   /** Contains right panel box information @public */
68   public showRightSideInfo: string = '';
69   /** Add the fixed class for the freeze @public */
70   public fixedClass: string = 'fixed';
71   /** Check the loading results @public */
72   public isLoadingResults: boolean = true;
73   /** Give the message for the loading @public */
74   public message: string = 'PLEASEWAIT';
75   /** Assign the forcesimulation active @public */
76   public forceSimulationActive: boolean = false;
77   /** Assign pinned class for the button when freezed @public */
78   public classApplied: boolean = false;
79   /** Contains sidebar open status @public */
80   public sideBarOpened: boolean = false;
81
82   /** Contains SVG attributes @private */
83   // tslint:disable-next-line:no-any
84   private svg: any;
85   /** Contains forced node animations @private */
86   // tslint:disable-next-line:no-any
87   private force: any;
88   /** Contains the Drag line */
89   // tslint:disable-next-line: no-any
90   private dragLine: any;
91   /** Contains id of the node @private */
92   private identifier: string;
93   /** Contains path information of the node */
94   // tslint:disable-next-line:no-any
95   private path: any;
96   /** Contains node network @private */
97   // tslint:disable-next-line:no-any
98   private network: any;
99   /** Contains node network @private */
100   // tslint:disable-next-line:no-any
101   private virutualDeploymentUnit: any;
102   /** Contains node connectionPoint @private */
103   // tslint:disable-next-line:no-any
104   private connectionPoint: any;
105   /** Contains node intConnectionPoint @private */
106   // tslint:disable-next-line:no-any
107   private intConnectionPoint: any;
108   /** Contains the node information @private */
109   private nodes: VNFDNODE[] = [];
110   /** Contains the link information of nodes @private */
111   private links: {}[] = [];
112   /** Instance of the rest service @private */
113   private restService: RestService;
114   /** Service holds the router information @private */
115   private router: Router;
116   /** Service contails all the shared service information @private */
117   private sharedService: SharedService;
118   /** Holds teh instance of AuthService class of type AuthService @private */
119   private activatedRoute: ActivatedRoute;
120   /** Notifier service to popup notification @private */
121   private notifierService: NotifierService;
122   /** Controls the header form @private */
123   private headers: HttpHeaders;
124   /** Contains tranlsate instance @private */
125   private translateService: TranslateService;
126   /** Rendered nodes represent network @private */
127   // tslint:disable-next-line:no-any
128   private gNetwork: any;
129   /** Rendered nodes represent VDU @private */
130   // tslint:disable-next-line:no-any
131   private gVirutualDeploymentUnit: any;
132   /** Rendered nodes represent connection point @private */
133   // tslint:disable-next-line:no-any
134   private gConnectionPoint: any;
135   /** Rendered nodes represent internal connection point @private */
136   // tslint:disable-next-line:no-any
137   private gIntConnectionPoint: any;
138   /** Contains all the information about VNF Details @private */
139   private vnfdPackageDetails: VNFDNODE;
140   /** Conatins mousedown action @private */
141   private mousedownNode: COMPOSERNODES = null;
142   /** Conatins mouseup action @private */
143   private mouseupNode: COMPOSERNODES = null;
144   /** Conatins current Selection node action @private */
145   private currentSelectedNode: COMPOSERNODES = null;
146   /** Add the activeNode for the selected @private */
147   private activeNode: string = 'active';
148   /** Contains lastkeypressed instance @private */
149   private lastKeyDown: number = -1;
150   /** Contains VDU Information @private */
151   private vduInfo: VDU;
152   /** Contains Internal VL Information @private */
153   private intvlInfo: InternalVLD;
154   /** Contains Connection Point Information @private */
155   private cpInfo: CONNECTIONPOINT;
156   /** Contains Internal Connection Point Information @private */
157   private intcpInfo: VLDInternalConnectionPoint;
158   /** Instance of the modal service @private */
159   private modalService: NgbModal;
160
161   constructor(injector: Injector) {
162     this.injector = injector;
163     this.restService = this.injector.get(RestService);
164     this.dataService = this.injector.get(DataService);
165     this.router = this.injector.get(Router);
166     this.activatedRoute = this.injector.get(ActivatedRoute);
167     this.notifierService = this.injector.get(NotifierService);
168     this.translateService = this.injector.get(TranslateService);
169     this.sharedService = this.injector.get(SharedService);
170     this.modalService = this.injector.get(NgbModal);
171   }
172   /**
173    * Lifecyle Hooks the trigger before component is instantiate
174    */
175   public ngOnInit(): void {
176     // tslint:disable-next-line:no-backbone-get-set-outside-model
177     this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
178     this.generateData();
179     this.headers = new HttpHeaders({
180       'Content-Type': 'application/zip',
181       Accept: 'application/json',
182       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
183     });
184   }
185
186   /** Prepare information for node creation of VNFD @public */
187   public generateData(): void {
188     this.nodes = []; this.links = []; this.vnfdPackageDetails = null;
189     this.showRightSideInfo = 'vnfdInfo';
190     const httpOptions: GETAPIURLHEADER = {
191       headers: new HttpHeaders({
192         'Content-Type': 'application/zip',
193         Accept: 'text/plain',
194         'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
195       }),
196       responseType: 'text'
197     };
198     this.restService.getResource(environment.VNFPACKAGES_URL + '/' + this.identifier + '/vnfd', httpOptions)
199       .subscribe((vnfdPackageDetails: VNFDNODE) => {
200         try {
201           const getJson: string = jsyaml.load(vnfdPackageDetails.toString(), { json: true });
202           if (getJson.hasOwnProperty('vnfd-catalog')) {
203             this.vnfdPackageDetails = getJson['vnfd-catalog'].vnfd[0];
204           } else if (getJson.hasOwnProperty('vnfd:vnfd-catalog')) {
205             this.vnfdPackageDetails = getJson['vnfd:vnfd-catalog'].vnfd[0];
206           } else if (getJson.hasOwnProperty('vnfd')) {
207             // tslint:disable-next-line: no-string-literal
208             this.vnfdPackageDetails = getJson['vnfd'][0];
209           }
210           this.generateCPPoint(this.vnfdPackageDetails);
211           this.generateVDU(this.vnfdPackageDetails);
212           this.generateInternalVLD(this.vnfdPackageDetails);
213           this.generateInternalCP(this.vnfdPackageDetails);
214           this.generateIntVLCPLinks(this.vnfdPackageDetails);
215           this.generateVDUCPLinks(this.vnfdPackageDetails);
216           this.createNode(this.nodes);
217           this.vnfdInfo.shortName = this.vnfdPackageDetails['short-name'];
218           this.vnfdInfo.description = this.vnfdPackageDetails.description;
219           this.vnfdInfo.version = this.vnfdPackageDetails.version;
220           this.vnfdInfo.id = this.vnfdPackageDetails.id;
221           this.vnfdInfo.name = this.vnfdPackageDetails.name;
222         } catch (e) {
223           this.notifierService.notify('error', this.translateService.instant('ERROR'));
224         }
225         this.isLoadingResults = false;
226       }, (error: ERRORDATA) => {
227         error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
228         if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
229           this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
230         } else {
231           this.restService.handleError(error, 'get');
232         }
233         this.isLoadingResults = false;
234         this.showRightSideInfo = '';
235       });
236   }
237   /** Events handles at drag on D3 region @public */
238   // tslint:disable-next-line:no-any
239   public drag(ev: any): void {
240     ev.dataTransfer.setData('text', ev.target.id);
241   }
242   /** Events handles drop at D3 region @public */
243   public drop(ev: DragEvent): void {
244     ev.preventDefault();
245     this.nodeTypeRef = ev.dataTransfer.getData('text');
246     if (this.nodeTypeRef === 'vdu') {
247       this.svg.selectAll('*').remove();
248       this.vduDropCompose();
249     } else if (this.nodeTypeRef === 'cp') {
250       this.svg.selectAll('*').remove();
251       this.cpDropCompose();
252     } else if (this.nodeTypeRef === 'intvl') {
253       this.svg.selectAll('*').remove();
254       this.intvlDropCompose();
255     }
256   }
257   /** Events handles allow drop on D3 region @public */
258   public allowDrop(ev: DragEvent): void {
259     ev.preventDefault();
260   }
261   /** Generate and list CP points @public */
262   public generateCPPoint(vnfdPackageDetails: VNFDNODE): void {
263     if (vnfdPackageDetails['connection-point'] !== undefined) {
264       vnfdPackageDetails['connection-point'].forEach((cp: CONNECTIONPOINT) => {
265         this.nodes.push({ id: cp.name, nodeTypeRef: 'cp', name: cp.name, type: cp.type });
266       });
267     }
268   }
269   /** Generate and list VDU @public */
270   public generateVDU(vnfdPackageDetails: VNFDNODE): void {
271     if (vnfdPackageDetails.vdu !== undefined) {
272       vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
273         this.nodes.push({
274           id: vdu.name, nodeTypeRef: 'vdu', 'cloud-init-file': vdu['cloud-init-file'], count: vdu.count, description: vdu.description,
275           vduID: vdu.id, name: vdu.name, interface: vdu.interface, 'vm-flavor': vdu['vm-flavor']
276         });
277       });
278     }
279   }
280   /** Generate and list Internal VLD @public */
281   public generateInternalVLD(vnfdPackageDetails: VNFDNODE): void {
282     if (vnfdPackageDetails['internal-vld'] !== undefined) {
283       vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
284         this.nodes.push({
285           id: internalVLD.name, nodeTypeRef: 'intvl', intVLID: internalVLD.id,
286           'internal-connection-point': internalVLD['internal-connection-point'],
287           'ip-profile-ref': internalVLD['ip-profile-ref'], name: internalVLD.name, 'short-name': internalVLD['short-name'],
288           type: internalVLD.type
289         });
290       });
291     }
292   }
293   /** Generate and list Internal CP @public */
294   public generateInternalCP(vnfdPackageDetails: VNFDNODE): void {
295     if (vnfdPackageDetails.vdu !== undefined) {
296       vnfdPackageDetails.vdu.forEach((intCP: VDUInternalConnectionPoint) => {
297         if (intCP['internal-connection-point'] !== undefined) {
298           intCP['internal-connection-point'].forEach((internalCP: VDUInternalConnectionPoint) => {
299             this.nodes.push({
300               id: internalCP.name, nodeTypeRef: 'intcp', name: internalCP.name,
301               'short-name': internalCP['short-name'], type: internalCP.type
302             });
303           });
304         }
305       });
306     }
307   }
308   /** Generate VDU External and Internal CP Links @public */
309   public generateVDUCPLinks(vnfdPackageDetails: VNFDNODE): void {
310     if (vnfdPackageDetails.vdu !== undefined) {
311       vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
312         const vduLink: string = vdu.name;
313         if (vdu.interface !== undefined) {
314           vdu.interface.forEach((interfaceDetails: VNFDInterface) => {
315             if (interfaceDetails['external-connection-point-ref'] !== undefined) {
316               this.links.push({ source: vduLink, target: interfaceDetails['external-connection-point-ref'] });
317             }
318             if (interfaceDetails['internal-connection-point-ref'] !== undefined) {
319               this.links.push({ source: vduLink, target: interfaceDetails['internal-connection-point-ref'] });
320             }
321           });
322         }
323       });
324     }
325   }
326   /** Generate Network/VLD/Internal VirtualLink, CP Links @public */
327   public generateIntVLCPLinks(vnfdPackageDetails: VNFDNODE): void {
328     if (vnfdPackageDetails['internal-vld'] !== undefined) {
329       vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
330         const vldName: string = internalVLD.name;
331         if (internalVLD['internal-connection-point'] !== undefined) {
332           internalVLD['internal-connection-point'].forEach((intCP: VLDInternalConnectionPoint) => {
333             this.links.push({ source: vldName, target: intCP['id-ref'] });
334           });
335         }
336       });
337     }
338   }
339   /** VNFD details can be saved on users inputs @public */
340   public saveVNFD(): void {
341     this.vnfdPackageDetails['short-name'] = this.vnfdInfo.shortName;
342     this.vnfdPackageDetails.description = this.vnfdInfo.description;
343     this.vnfdPackageDetails.version = this.vnfdInfo.version;
344     this.vnfdPackageDetails.id = this.vnfdInfo.id;
345     this.vnfdPackageDetails.name = this.vnfdInfo.name;
346     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
347     delete this.vnfdPackageDetails.shortName;
348   }
349   /** VDU details can be saved on users inputs @public */
350   public saveVDU(vduID: string): void {
351     this.vnfdPackageDetails.vdu.forEach((ref: VDU) => {
352       if (ref.id === vduID) {
353         ref.count = this.vduInfo.count;
354         ref.description = this.vduInfo.description;
355         ref.image = this.vduInfo.image;
356         ref.id = this.vduInfo.id;
357         ref.name = this.vduInfo.name;
358       }
359     });
360     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
361   }
362   /** IntVL details can be saved on users inputs @public */
363   public saveIntVL(intVLID: string): void {
364     this.vnfdPackageDetails['internal-vld'].forEach((ref: InternalVLD) => {
365       if (ref.id === intVLID) {
366         ref['short-name'] = this.intvlInfo.shortName;
367         ref.name = this.intvlInfo.name;
368         ref.type = this.intvlInfo.type;
369         ref['ip-profile-ref'] = !isNullOrUndefined(this.intvlInfo.ipProfileRef) ? this.intvlInfo.ipProfileRef : '';
370         ref.id = this.intvlInfo.id;
371         delete ref.shortName;
372         delete ref.ipProfileRef;
373       }
374     });
375     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
376   }
377   /** IntVL details can be saved on users inputs @public */
378   public saveCP(cpName: string): void {
379     this.vnfdPackageDetails['connection-point'].forEach((ref: CONNECTIONPOINT) => {
380       if (ref.name === cpName) {
381         if (!isNullOrUndefined(this.cpInfo.type)) {
382           ref.type = this.cpInfo.type;
383         }
384         ref.name = this.cpInfo.name;
385       }
386     });
387     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
388   }
389   /** Edit topology @public */
390   public onEdit(): void {
391     this.router.navigate(['/packages/vnf/edit/', this.identifier]).catch();
392   }
393   /** Show Info @public */
394   public showInfo(): void {
395     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
396     modalRef.componentInstance.topologyType = 'Info';
397     modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
398     modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
399       if (result) {
400         // empty
401       }
402     }).catch();
403   }
404   /** Event to freeze the animation @public */
405   public onFreeze(): void {
406     this.classApplied = !this.classApplied;
407     const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
408     d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
409     if (alreadyFixedIsActive) {
410       this.force.stop();
411     }
412     this.forceSimulationActive = alreadyFixedIsActive;
413     this.nodes.forEach((d: COMPOSERNODES) => {
414       d.fx = (alreadyFixedIsActive) ? null : d.x;
415       d.fy = (alreadyFixedIsActive) ? null : d.y;
416     });
417     if (alreadyFixedIsActive) {
418       this.force.restart();
419     }
420   }
421   /** Events handles when dragended @public */
422   public toggleSidebar(): void {
423     this.sideBarOpened = !this.sideBarOpened;
424     this.deselectAllNodes();
425     this.showRightSideInfo = 'vnfdInfo';
426   }
427   /** Get the default Configuration of containers @private */
428   private getGraphContainerAttr(): GRAPHDETAILS {
429     return {
430       width: 700,
431       height: 400,
432       nodeHeight: 50,
433       nodeWidth: 35,
434       textX: -35,
435       textY: 30,
436       radius: 5,
437       distance: 50,
438       strength: -500,
439       forcex: 2,
440       forcey: 2,
441       sourcePaddingYes: 17,
442       sourcePaddingNo: 12,
443       targetPaddingYes: 4,
444       targetPaddingNo: 3,
445       alphaTarget: 0.3,
446       imageX: -25,
447       imageY: -25,
448       shiftKeyCode: 17
449     };
450   }
451   /** Node is created and render at D3 region @private */
452   private createNode(nodes: VNFDNODE[]): void {
453     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
454     d3.selectAll('svg#graphContainer > *').remove();
455     d3.select(window).on('keydown', () => { this.keyDown(); });
456     d3.select(window).on('keyup', () => { this.keyUp(); });
457     this.svg = d3.select('#graphContainer').attr('oncontextmenu', 'return false;').attr('width', graphContainerAttr.width)
458       .attr('height', graphContainerAttr.height).on('mousemove', () => { this.mousemove(); });
459     this.force = d3.forceSimulation()
460       .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance))
461       .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
462       .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
463       .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
464       .on('tick', () => { this.tick(); });
465     this.path = this.svg.append('svg:g').selectAll('path');
466     this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
467     this.network = this.svg.append('svg:g').selectAll('network');
468     this.virutualDeploymentUnit = this.svg.append('svg:g').selectAll('virutualDeploymentUnit');
469     this.connectionPoint = this.svg.append('svg:g').selectAll('connectionPoint');
470     this.intConnectionPoint = this.svg.append('svg:g').selectAll('intConnectionPoint');
471     this.restart(nodes);
472   }
473   /** Update force layout (called automatically each iteration) @private */
474   private tick(): void {
475     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
476     this.path.attr('d', (d: Tick) => {
477       const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y;
478       const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
479       const normX: number = deltaX / dist; const normY: number = deltaY / dist;
480       const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
481       const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
482       const sourceX: number = d.source.x + (sourcePadding * normX); const sourceY: number = d.source.y + (sourcePadding * normY);
483       const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY);
484       return `M${sourceX},${sourceY}L${targetX},${targetY}`;
485     }).on('dblclick', (d: Tick) => { this.getDeleteLinkConfirmation(d); });
486     this.network.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
487     this.virutualDeploymentUnit.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
488     this.connectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
489     this.intConnectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
490   }
491   /** Update graph (called when needed) @private */
492   private restart(nodes: VNFDNODE[]): void {
493     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
494     this.path = this.path.data(this.links);
495     const cpNodes: {}[] = []; const vduNodes: {}[] = []; const vlNodes: {}[] = []; const intcpNodes: {}[] = []; //Nodes are known by id
496     nodes.forEach((nodeList: VNFDNODE) => {
497       if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); }
498       else if (nodeList.nodeTypeRef === 'vdu') { vduNodes.push(nodeList); }
499       else if (nodeList.nodeTypeRef === 'intvl') { vlNodes.push(nodeList); }
500       else if (nodeList.nodeTypeRef === 'intcp') { intcpNodes.push(nodeList); }
501     });
502     this.network = this.network.data(vlNodes, (d: { id: number }) => d.id);
503     this.virutualDeploymentUnit = this.virutualDeploymentUnit.data(vduNodes, (d: { id: number }) => d.id);
504     this.connectionPoint = this.connectionPoint.data(cpNodes, (d: { id: number }) => d.id);
505     this.intConnectionPoint = this.intConnectionPoint.data(intcpNodes, (d: { id: number }) => d.id);
506     this.resetAndCreateNodes();
507     this.force.nodes(nodes).force('link').links(this.links); //Set the graph in motion
508     this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
509   }
510   /** Rest and create nodes @private */
511   private resetAndCreateNodes(): void {
512     this.path.exit().remove();
513     this.network.exit().remove();
514     this.virutualDeploymentUnit.exit().remove();
515     this.connectionPoint.exit().remove();
516     this.intConnectionPoint.exit().remove();
517     this.getPathNodes();
518     this.getgNetwork();
519     this.getgVirutualDeploymentUnit();
520     this.getgConnectionPoint();
521     this.getgIntConnectionPoint();
522     this.network = this.gNetwork.merge(this.network);
523     this.virutualDeploymentUnit = this.gVirutualDeploymentUnit.merge(this.virutualDeploymentUnit);
524     this.connectionPoint = this.gConnectionPoint.merge(this.connectionPoint);
525     this.intConnectionPoint = this.gIntConnectionPoint.merge(this.intConnectionPoint);
526     this.path.merge(this.path);
527   }
528   /** Setting the Path @private */
529   private getPathNodes(): void {
530     this.path = this.path.enter().append('svg:path').attr('class', 'link');
531   }
532   /** Settings all the network attributes of nodes @private */
533   private getgNetwork(): void {
534     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
535     this.gNetwork = this.network.enter().append('svg:g');
536     this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
537     this.gNetwork.append('svg:image')
538       .style('opacity', 1)
539       .attr('x', graphContainerAttr.imageX)
540       .attr('y', graphContainerAttr.imageY)
541       .attr('id', (d: VNFDNODE) => { return d.id; })
542       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
543       .attr('xlink:href', 'assets/images/INTVL.svg')
544       .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
545       .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
546       .on('click', (d: VNFDNODE) => { this.singleClick(this.network, d); this.onNodeClickToggleSidebar(); })
547       .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
548     this.gNetwork.append('svg:text')
549       .attr('class', 'node_text')
550       .attr('y', graphContainerAttr.textY)
551       .text((d: { id: number }) => d.id);
552   }
553   /** Settings all the connection point attributes of nodes @private */
554   private getgVirutualDeploymentUnit(): void {
555     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
556     this.gVirutualDeploymentUnit = this.virutualDeploymentUnit.enter().append('svg:g');
557     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
558     this.gVirutualDeploymentUnit.append('svg:image')
559       .style('opacity', 1)
560       .attr('x', graphContainerAttr.imageX)
561       .attr('y', graphContainerAttr.imageY)
562       .attr('id', (d: VNFDNODE) => { return d.id; })
563       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
564       .attr('xlink:href', 'assets/images/VDU.svg')
565       .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
566       .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
567       .on('click', (d: VNFDNODE) => { this.singleClick(this.virutualDeploymentUnit, d); this.onNodeClickToggleSidebar(); })
568       .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
569     this.gVirutualDeploymentUnit.append('svg:text')
570       .attr('class', 'node_text')
571       .attr('y', graphContainerAttr.textY)
572       .text((d: { id: string }) => d.id);
573   }
574   /** Settings all the connection point attributes of nodes @private */
575   private getgConnectionPoint(): void {
576     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
577     this.gConnectionPoint = this.connectionPoint.enter().append('svg:g');
578     this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
579     this.gConnectionPoint.append('svg:image')
580       .style('opacity', 1)
581       .attr('x', graphContainerAttr.imageX)
582       .attr('y', graphContainerAttr.imageY)
583       .attr('id', (d: VNFDNODE) => { return d.id; })
584       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
585       .attr('xlink:href', 'assets/images/CP-VNF.svg')
586       .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
587       .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
588       .on('click', (d: VNFDNODE) => { this.singleClick(this.connectionPoint, d); this.onNodeClickToggleSidebar(); })
589       .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
590     this.gConnectionPoint.append('svg:text')
591       .attr('class', 'node_text')
592       .attr('y', graphContainerAttr.textY)
593       .text((d: { id: string }) => d.id);
594   }
595   /** Settings all the internal connection point attributes of nodes @private */
596   private getgIntConnectionPoint(): void {
597     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
598     this.gIntConnectionPoint = this.intConnectionPoint.enter().append('svg:g');
599     this.gIntConnectionPoint.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
600     this.gIntConnectionPoint.append('svg:image')
601       .style('opacity', 1)
602       .attr('x', graphContainerAttr.imageX)
603       .attr('y', graphContainerAttr.imageY)
604       .attr('id', (d: VNFDNODE) => { return d.id; })
605       .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
606       .attr('xlink:href', 'assets/images/INTCP.svg')
607       .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
608       .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
609       .on('click', (d: VNFDNODE) => { this.singleClick(this.intConnectionPoint, d); this.onNodeClickToggleSidebar(); })
610       .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
611     this.gIntConnectionPoint.append('svg:text')
612       .attr('class', 'node_text')
613       .attr('y', graphContainerAttr.textY)
614       .text((d: { id: string }) => d.id);
615   }
616   /** Drop VDU Composer Data @private */
617   private vduDropCompose(): void {
618     const randomID: string = this.sharedService.randomString();
619     const vduNode: VNFDNODE[] = [{
620       nodeTypeRef: 'vdu', id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
621       interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
622     }];
623     const nodeCopy: VNFDNODE[] = this.nodes;
624     Array.prototype.push.apply(vduNode, nodeCopy);
625     this.nodes = vduNode;
626     if (this.vnfdPackageDetails.vdu === undefined) { this.vnfdPackageDetails.vdu = []; }
627     this.vnfdPackageDetails.vdu.push({
628       id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
629       interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
630     });
631     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
632   }
633   /** Drop CP Composer Data @private */
634   private cpDropCompose(): void {
635     const randomID: string = this.sharedService.randomString();
636     const cpNode: VNFDNODE[] = [{ nodeTypeRef: 'cp', id: 'cp_' + randomID, name: 'cp_' + randomID }];
637     const nodeCopy: VNFDNODE[] = this.nodes;
638     Array.prototype.push.apply(cpNode, nodeCopy);
639     this.nodes = cpNode;
640     if (this.vnfdPackageDetails['connection-point'] === undefined) {
641       this.vnfdPackageDetails['connection-point'] = [];
642     }
643     this.vnfdPackageDetails['connection-point'].push({
644       id: 'cp_' + randomID, name: 'cp_' + randomID, type: 'VPORT'
645     });
646     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
647   }
648   /** Drop IntVL Composer Data @private */
649   private intvlDropCompose(): void {
650     const randomID: string = this.sharedService.randomString();
651     const intvlNode: VNFDNODE[] = [{
652       nodeTypeRef: 'intvl', id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID, 'ip-profile-ref': '',
653       type: 'ELAN'
654     }];
655     const nodeCopy: VNFDNODE[] = this.nodes;
656     Array.prototype.push.apply(intvlNode, nodeCopy);
657     this.nodes = intvlNode;
658     if (this.vnfdPackageDetails['internal-vld'] === undefined) { this.vnfdPackageDetails['internal-vld'] = []; }
659     this.vnfdPackageDetails['internal-vld'].push({
660       id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID,
661       'ip-profile-ref': '', type: 'ELAN', 'internal-connection-point': []
662     });
663     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
664   }
665   /** Add the Add Nodes Data @private */
666   private addNodes(apiURL: string, identifier: string, data: VNFDNODE): void {
667     this.isLoadingResults = true;
668     const apiURLHeader: APIURLHEADER = {
669       url: apiURL + '/' + identifier + '/package_content',
670       httpOptions: { headers: this.headers }
671     };
672     const vnfData: {} = {};
673     vnfData['vnfd:vnfd-catalog'] = {};
674     vnfData['vnfd:vnfd-catalog'].vnfd = [];
675     vnfData['vnfd:vnfd-catalog'].vnfd.push(data);
676     const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
677     this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
678       .then((content: ArrayBuffer): void => {
679         this.restService.putResource(apiURLHeader, content).subscribe((res: {}) => {
680           this.generateData();
681           this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
682           this.isLoadingResults = false;
683         }, (error: ERRORDATA) => {
684           this.generateData();
685           this.restService.handleError(error, 'put');
686           this.isLoadingResults = false;
687         });
688       }).catch((): void => {
689         this.notifierService.notify('error', this.translateService.instant('ERROR'));
690         this.isLoadingResults = false;
691       });
692   }
693   /** Events handles when mousedown click it will capture the selected node data @private */
694   private mouseDown(d: VNFDNODE): void {
695     event.preventDefault();
696     if (d3.event.ctrlKey) { return; }
697     if (d3.event.shiftKey) {
698       this.mousedownNode = d;
699       this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
700       this.dragLine.classed('hidden', false)
701         .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
702     }
703   }
704   /** Event handles when mouseup event occures @private */
705   private mouseUp(d: VNFDNODE): void {
706     if (!this.mousedownNode) { return; }
707     this.dragLine.classed('hidden', true);
708     this.mouseupNode = d;
709     if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intcp') {
710       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
711       this.deselectPath();
712     }
713     else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'vdu') {
714       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
715       this.deselectPath();
716     }
717     else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'vdu') {
718       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
719       this.deselectPath();
720     }
721     else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intvl') {
722       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
723       this.deselectPath();
724     }
725     else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'cp') {
726       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
727       this.deselectPath();
728     }
729     else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'cp') {
730       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
731       this.deselectPath();
732     }
733     else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intcp') {
734       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
735       this.deselectPath();
736     } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'cp') {
737       this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
738         if (vduDetails.id === this.mousedownNode.id) {
739           if (vduDetails.interface === undefined) { vduDetails.interface = []; }
740           vduDetails.interface.push({
741             'external-connection-point-ref': this.mouseupNode.id, 'mgmt-interface': true,
742             name: 'eth_' + this.sharedService.randomString(),
743             'virtual-interface': { type: 'VIRTIO' },
744             type: 'EXTERNAL'
745           });
746           if (vduDetails['internal-connection-point'] === undefined) {
747             vduDetails['internal-connection-point'] = [];
748           }
749           if (vduDetails['monitoring-param'] === undefined) {
750             vduDetails['monitoring-param'] = [];
751           }
752           if (vduDetails['vm-flavor'] === undefined) {
753             vduDetails['vm-flavor'] = {};
754           }
755         }
756       });
757       this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
758       this.deselectPath();
759     } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intvl') {
760       const setIntCP: string = 'intcp_' + this.sharedService.randomString();
761       this.vnfdPackageDetails['internal-vld'].forEach((vldInternal: InternalVLD) => {
762         if (vldInternal.id === this.mouseupNode.id) {
763           if (vldInternal['internal-connection-point'] === undefined) { vldInternal['internal-connection-point'] = []; }
764           vldInternal['internal-connection-point'].push({ 'id-ref': setIntCP });
765         }
766       });
767       this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
768         if (vduDetails.id === this.mousedownNode.id) {
769           if (vduDetails.interface === undefined) {
770             vduDetails.interface = [];
771           }
772           vduDetails.interface.push({
773             'internal-connection-point-ref': setIntCP, name: 'int_' + setIntCP, type: 'INTERNAL', 'virtual-interface': { type: 'VIRTIO' }
774           });
775           if (vduDetails['internal-connection-point'] === undefined) {
776             vduDetails['internal-connection-point'] = [];
777           }
778           vduDetails['internal-connection-point'].push({
779             id: setIntCP, name: setIntCP, 'short-name': setIntCP, type: 'VPORT'
780           });
781         }
782       });
783       this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
784       this.deselectPath();
785     }
786     else {
787       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
788       this.deselectPath();
789     }
790     this.resetMouseActions();
791     this.currentSelectedNode = null;
792   }
793   /** Events handles when mousemove it will capture the selected node data @private */
794   private mousemove(): void {
795     if (!this.mousedownNode) { return; }
796     this.dragLine.attr('d',
797       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
798   }
799   /** reset Mouse varaibles @private */
800   private resetMouseActions(): void {
801     this.mousedownNode = null;
802     this.mouseupNode = null;
803   }
804   /** Key press event @private */
805   private keyDown(): void {
806     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
807     if (this.lastKeyDown !== -1) { return; }
808     this.lastKeyDown = d3.event.keyCode;
809     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
810       this.gNetwork.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
811       this.gVirutualDeploymentUnit.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
812       this.gConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
813       this.gIntConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
814       this.svg.classed('ctrl', true);
815     }
816   }
817   /** Key realse event @private */
818   private keyUp(): void {
819     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
820     this.lastKeyDown = -1;
821     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
822       this.gNetwork.on('.drag', null);
823       this.gVirutualDeploymentUnit.on('.drag', null);
824       this.gConnectionPoint.on('.drag', null);
825       this.gIntConnectionPoint.on('.drag', null);
826       this.svg.classed('ctrl', false);
827     }
828   }
829   /** Mosue Drag Line false if it is not satisfied @private */
830   private deselectPath(): void {
831     this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
832   }
833   /** Events handles when Shift Click to perform create cp @private */
834   // tslint:disable-next-line: no-any
835   private singleClick(nodeSelected: any, d: VNFDNODE): void {
836     this.selectedNode(nodeSelected, d);
837   }
838   /** Get confirmation Before Deleting the Node in Topology @private */
839   private getDeleteNodeConfirmation(d: VNFDNODE): void {
840     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
841     modalRef.componentInstance.topologyType = 'Delete';
842     modalRef.componentInstance.topologyname = d.name;
843     if (d.nodeTypeRef === 'vdu') {
844       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
845     } else if (d.nodeTypeRef === 'intvl') {
846       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
847     } else if (d.nodeTypeRef === 'cp') {
848       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
849     } else if (d.nodeTypeRef === 'intcp') {
850       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
851     }
852     modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
853       if (result) {
854         this.deleteNode(d);
855       }
856     }).catch();
857   }
858   /** Delete nodes @private */
859   private deleteNode(d: VNFDNODE): void {
860     const deletedNode: VNFDNODE = d;
861     this.nodes.forEach((node: VNFDNODE) => {
862       if (node.id === d.id) {
863         if (deletedNode.nodeTypeRef === 'cp') {
864           if (this.vnfdPackageDetails.vdu !== undefined) {
865             this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
866               if (vduDetails.interface !== undefined) {
867                 const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['external-connection-point-ref']; })
868                   .indexOf(d.id);
869                 if (interfacePos >= 0) {
870                   vduDetails.interface.splice(interfacePos, 1);
871                 }
872               }
873             });
874           }
875           const cpPos: number = this.vnfdPackageDetails['connection-point'].map((e: CONNECTIONPOINT) => { return e.name; })
876             .indexOf(d.id);
877           if (cpPos >= 0) {
878             this.vnfdPackageDetails['connection-point'].splice(cpPos, 1);
879           }
880         } else if (deletedNode.nodeTypeRef === 'intcp') {
881           this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
882             // Delete Interface
883             const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['internal-connection-point-ref']; })
884               .indexOf(d.id);
885             if (interfacePos >= 0) {
886               vduDetails.interface.splice(interfacePos, 1);
887             }
888             // Delete Internal CP
889             const interCPPos: number = vduDetails['internal-connection-point']
890               .map((e: VDUInternalConnectionPoint) => { return e.id; })
891               .indexOf(d.id);
892             if (interCPPos >= 0) {
893               vduDetails['internal-connection-point'].splice(interCPPos, 1);
894             }
895           });
896           if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
897             this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
898               const interfacePos: number = internalVLD['internal-connection-point']
899                 .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(d.id);
900               if (interfacePos >= 0) {
901                 internalVLD['internal-connection-point'].splice(interfacePos, 1);
902               }
903             });
904           }
905         } else if (deletedNode.nodeTypeRef === 'intvl') {
906           const intvlPos: number = this.vnfdPackageDetails['internal-vld']
907             .map((e: InternalVLD) => { return e.name; }).indexOf(d.id);
908           if (intvlPos >= 0) {
909             this.vnfdPackageDetails['internal-vld'].splice(intvlPos, 1);
910           }
911         } else if (deletedNode.nodeTypeRef === 'vdu') {
912           const internalCPList: string[] = [];
913           if (deletedNode.interface !== undefined && deletedNode.interface.length > 0) {
914             deletedNode.interface.forEach((interfaceNode: InternalVLD) => {
915               if (interfaceNode['internal-connection-point-ref'] !== undefined) {
916                 internalCPList.push(interfaceNode['internal-connection-point-ref']);
917               }
918             });
919           }
920           internalCPList.forEach((list: string) => {
921             if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
922               this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
923                 const interfacePos: number = internalVLD['internal-connection-point']
924                   .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(list);
925                 if (interfacePos >= 0) {
926                   internalVLD['internal-connection-point'].splice(interfacePos, 1);
927                 }
928               });
929             }
930           });
931           const vduPos: number = this.vnfdPackageDetails.vdu.map((e: VDU) => { return e.id; }).indexOf(d.id);
932           if (vduPos >= 0) {
933             this.vnfdPackageDetails.vdu.splice(vduPos, 1);
934           }
935         } else {
936           this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
937         }
938         this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
939       }
940     });
941   }
942   /** Get confirmation before deleting the ink in Topology @private */
943   private getDeleteLinkConfirmation(d: Tick): void {
944     this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
945   }
946   /** Selected nodes @private */
947   // tslint:disable-next-line: no-any
948   private selectedNode(nodeSeleced: any, d: VNFDNODE): void {
949     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
950     this.deselectAllNodes();
951     nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
952     if (d.nodeTypeRef === 'vdu' && !alreadyIsActive) {
953       this.vnfdPackageDetails.vdu.forEach((res: VDU) => {
954         if (res.name === d.id) {
955           this.showRightSideInfo = 'vduInfo';
956           this.vduInfo = res;
957         }
958       });
959     } else if (d.nodeTypeRef === 'intvl' && !alreadyIsActive) {
960       this.vnfdPackageDetails['internal-vld'].forEach((res: InternalVLD) => {
961         if (res.name === d.id) {
962           this.showRightSideInfo = 'intvlInfo';
963           this.intvlInfo = res;
964           this.intvlInfo.shortName = res['short-name'];
965           this.intvlInfo.ipProfileRef = res['ip-profile-ref'];
966         }
967       });
968     } else if (d.nodeTypeRef === 'cp' && !alreadyIsActive) {
969       this.vnfdPackageDetails['connection-point'].forEach((res: CONNECTIONPOINT) => {
970         if (res.name === d.id) {
971           this.showRightSideInfo = 'cpInfo';
972           this.cpInfo = res;
973         }
974       });
975     }
976     else if (d.nodeTypeRef === 'intcp' && !alreadyIsActive) {
977       this.intcpInfo = d;
978       this.showRightSideInfo = 'intcpInfo';
979       this.intcpInfo.shortName = d['short-name'];
980     } else {
981       this.showRightSideInfo = 'vnfdInfo';
982     }
983   }
984   /** De-select all the selected nodes @private */
985   private deselectAllNodes(): void {
986     this.network.select('image').classed(this.activeNode, false);
987     this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
988     this.connectionPoint.select('image').classed(this.activeNode, false);
989     this.intConnectionPoint.select('image').classed(this.activeNode, false);
990   }
991   /** Events handles when dragstarted @private */
992   private dragstarted(d: COMPOSERNODES): void {
993     d.fx = d.x;
994     d.fy = d.y;
995   }
996   /** Events handles when dragged @private */
997   private dragged(d: COMPOSERNODES): void {
998     d.fx = d.x = d3.event.x;
999     d.fy = d.y = d3.event.y;
1000   }
1001   /** Events handles when dragended @private */
1002   private dragended(d: COMPOSERNODES): void {
1003     if (this.forceSimulationActive) {
1004       d.fx = null;
1005       d.fy = null;
1006     } else {
1007       d.fx = d.x;
1008       d.fy = d.y;
1009       this.forceSimulationActive = false;
1010     }
1011   }
1012   /** Events handles when node double click   @private */
1013   private onNodedblClickToggleSidebar(): void {
1014     this.sideBarOpened = false;
1015   }
1016   /** Events handles when node single click   @private */
1017   private onNodeClickToggleSidebar(): void {
1018     this.sideBarOpened = true;
1019   }
1020 }