NG-UI Added the validation for the topology connection.
[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') {
710       this.vduMouseDownNode();
711     } else if (this.mousedownNode.nodeTypeRef === 'cp') {
712       this.cpMouseDownNode();
713     } else if (this.mousedownNode.nodeTypeRef === 'intvl') {
714       this.intVLMouseDownNode();
715     } else if (this.mousedownNode.nodeTypeRef === 'intcp') {
716       this.intCPMouseDownNode();
717     } else {
718       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
719       this.deselectPath();
720     }
721     this.resetMouseActions();
722     this.currentSelectedNode = null;
723   }
724   /** Establish a connection point between vdu and other nodes @private */
725   private vduMouseDownNode(): void {
726     if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'cp') {
727       this.vduCPConnection(this.mousedownNode.id, this.mouseupNode.id);
728     } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intcp') {
729       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
730       this.deselectPath();
731     } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'vdu') {
732       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
733       this.deselectPath();
734     } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intvl') {
735       this.vduIntvlConnection(this.mousedownNode.id, this.mouseupNode.id);
736     }
737   }
738
739   /** Establish a connection point between cp and other nodes @private */
740   private cpMouseDownNode(): void {
741     if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'vdu') {
742       this.vduCPConnection(this.mouseupNode.id, this.mousedownNode.id);
743     } else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intvl') {
744       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
745       this.deselectPath();
746     } else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intcp') {
747       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
748       this.deselectPath();
749     } else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'cp') {
750       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDCP'));
751       this.deselectPath();
752     }
753   }
754
755   /** Establish a connection piont between intvl and other nodes @private */
756   private intVLMouseDownNode(): void {
757     if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'cp') {
758       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
759       this.deselectPath();
760     } else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'vdu') {
761       this.vduIntvlConnection(this.mouseupNode.id, this.mousedownNode.id);
762     } else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'intvl') {
763       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDVNFVL'));
764       this.deselectPath();
765     } else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'intcp') {
766       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDONTCP'));
767       this.deselectPath();
768     }
769   }
770
771   /** Establish a connection point between intcp and other nodes @private */
772   private intCPMouseDownNode(): void {
773     if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'vdu') {
774       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
775       this.deselectPath();
776     } else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'cp') {
777       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
778       this.deselectPath();
779     } else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'intvl') {
780       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVNFVL'));
781       this.deselectPath();
782     } else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'intcp') {
783       this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDINTCP'));
784       this.deselectPath();
785     }
786   }
787
788   /** Establish a connection between VDU & CP vice versa @private */
789   private vduCPConnection(nodeA: string, nodeB: string): void {
790     this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
791       if (vduDetails.id === nodeA) {
792         if (vduDetails.interface === undefined) { vduDetails.interface = []; }
793         vduDetails.interface.push({
794           'external-connection-point-ref': nodeB, 'mgmt-interface': true,
795           name: 'eth_' + this.sharedService.randomString(),
796           'virtual-interface': { type: 'VIRTIO' },
797           type: 'EXTERNAL'
798         });
799         if (vduDetails['internal-connection-point'] === undefined) {
800           vduDetails['internal-connection-point'] = [];
801         }
802         if (vduDetails['monitoring-param'] === undefined) {
803           vduDetails['monitoring-param'] = [];
804         }
805         if (vduDetails['vm-flavor'] === undefined) {
806           vduDetails['vm-flavor'] = {};
807         }
808       }
809     });
810     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
811     this.deselectPath();
812   }
813
814   /** Establish a connection between vdu & intvl and vice versa @private */
815   private vduIntvlConnection(nodeA: string, nodeB: string): void {
816     const setIntCP: string = 'intcp_' + this.sharedService.randomString();
817     this.vnfdPackageDetails['internal-vld'].forEach((vldInternal: InternalVLD) => {
818       if (vldInternal.id === nodeB) {
819         if (vldInternal['internal-connection-point'] === undefined) { vldInternal['internal-connection-point'] = []; }
820         vldInternal['internal-connection-point'].push({ 'id-ref': setIntCP });
821       }
822     });
823     this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
824       if (vduDetails.id === nodeA) {
825         if (vduDetails.interface === undefined) {
826           vduDetails.interface = [];
827         }
828         vduDetails.interface.push({
829           'internal-connection-point-ref': setIntCP, name: 'int_' + setIntCP, type: 'INTERNAL', 'virtual-interface': { type: 'VIRTIO' }
830         });
831         if (vduDetails['internal-connection-point'] === undefined) {
832           vduDetails['internal-connection-point'] = [];
833         }
834         vduDetails['internal-connection-point'].push({
835           id: setIntCP, name: setIntCP, 'short-name': setIntCP, type: 'VPORT'
836         });
837       }
838     });
839     this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
840     this.deselectPath();
841   }
842
843   /** Events handles when mousemove it will capture the selected node data @private */
844   private mousemove(): void {
845     if (!this.mousedownNode) { return; }
846     this.dragLine.attr('d',
847       `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
848   }
849   /** reset Mouse varaibles @private */
850   private resetMouseActions(): void {
851     this.mousedownNode = null;
852     this.mouseupNode = null;
853   }
854   /** Key press event @private */
855   private keyDown(): void {
856     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
857     if (this.lastKeyDown !== -1) { return; }
858     this.lastKeyDown = d3.event.keyCode;
859     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
860       this.gNetwork.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
861       this.gVirutualDeploymentUnit.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
862       this.gConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
863       this.gIntConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
864       this.svg.classed('ctrl', true);
865     }
866   }
867   /** Key realse event @private */
868   private keyUp(): void {
869     const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
870     this.lastKeyDown = -1;
871     if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
872       this.gNetwork.on('.drag', null);
873       this.gVirutualDeploymentUnit.on('.drag', null);
874       this.gConnectionPoint.on('.drag', null);
875       this.gIntConnectionPoint.on('.drag', null);
876       this.svg.classed('ctrl', false);
877     }
878   }
879   /** Mosue Drag Line false if it is not satisfied @private */
880   private deselectPath(): void {
881     this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
882   }
883   /** Events handles when Shift Click to perform create cp @private */
884   // tslint:disable-next-line: no-any
885   private singleClick(nodeSelected: any, d: VNFDNODE): void {
886     this.selectedNode(nodeSelected, d);
887   }
888   /** Get confirmation Before Deleting the Node in Topology @private */
889   private getDeleteNodeConfirmation(d: VNFDNODE): void {
890     const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
891     modalRef.componentInstance.topologyType = 'Delete';
892     modalRef.componentInstance.topologyname = d.name;
893     if (d.nodeTypeRef === 'vdu') {
894       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
895     } else if (d.nodeTypeRef === 'intvl') {
896       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
897     } else if (d.nodeTypeRef === 'cp') {
898       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
899     } else if (d.nodeTypeRef === 'intcp') {
900       modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
901     }
902     modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
903       if (result) {
904         this.deleteNode(d);
905       }
906     }).catch();
907   }
908   /** Delete nodes @private */
909   private deleteNode(d: VNFDNODE): void {
910     const deletedNode: VNFDNODE = d;
911     this.nodes.forEach((node: VNFDNODE) => {
912       if (node.id === d.id) {
913         if (deletedNode.nodeTypeRef === 'cp') {
914           if (this.vnfdPackageDetails.vdu !== undefined) {
915             this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
916               if (vduDetails.interface !== undefined) {
917                 const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['external-connection-point-ref']; })
918                   .indexOf(d.id);
919                 if (interfacePos >= 0) {
920                   vduDetails.interface.splice(interfacePos, 1);
921                 }
922               }
923             });
924           }
925           const cpPos: number = this.vnfdPackageDetails['connection-point'].map((e: CONNECTIONPOINT) => { return e.name; })
926             .indexOf(d.id);
927           if (cpPos >= 0) {
928             this.vnfdPackageDetails['connection-point'].splice(cpPos, 1);
929           }
930         } else if (deletedNode.nodeTypeRef === 'intcp') {
931           this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
932             // Delete Interface
933             const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['internal-connection-point-ref']; })
934               .indexOf(d.id);
935             if (interfacePos >= 0) {
936               vduDetails.interface.splice(interfacePos, 1);
937             }
938             // Delete Internal CP
939             const interCPPos: number = vduDetails['internal-connection-point']
940               .map((e: VDUInternalConnectionPoint) => { return e.id; })
941               .indexOf(d.id);
942             if (interCPPos >= 0) {
943               vduDetails['internal-connection-point'].splice(interCPPos, 1);
944             }
945           });
946           if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
947             this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
948               const interfacePos: number = internalVLD['internal-connection-point']
949                 .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(d.id);
950               if (interfacePos >= 0) {
951                 internalVLD['internal-connection-point'].splice(interfacePos, 1);
952               }
953             });
954           }
955         } else if (deletedNode.nodeTypeRef === 'intvl') {
956           const intvlPos: number = this.vnfdPackageDetails['internal-vld']
957             .map((e: InternalVLD) => { return e.name; }).indexOf(d.id);
958           if (intvlPos >= 0) {
959             this.vnfdPackageDetails['internal-vld'].splice(intvlPos, 1);
960           }
961         } else if (deletedNode.nodeTypeRef === 'vdu') {
962           const internalCPList: string[] = [];
963           if (deletedNode.interface !== undefined && deletedNode.interface.length > 0) {
964             deletedNode.interface.forEach((interfaceNode: InternalVLD) => {
965               if (interfaceNode['internal-connection-point-ref'] !== undefined) {
966                 internalCPList.push(interfaceNode['internal-connection-point-ref']);
967               }
968             });
969           }
970           internalCPList.forEach((list: string) => {
971             if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
972               this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
973                 const interfacePos: number = internalVLD['internal-connection-point']
974                   .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(list);
975                 if (interfacePos >= 0) {
976                   internalVLD['internal-connection-point'].splice(interfacePos, 1);
977                 }
978               });
979             }
980           });
981           const vduPos: number = this.vnfdPackageDetails.vdu.map((e: VDU) => { return e.id; }).indexOf(d.id);
982           if (vduPos >= 0) {
983             this.vnfdPackageDetails.vdu.splice(vduPos, 1);
984           }
985         } else {
986           this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
987         }
988         this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
989       }
990     });
991   }
992   /** Get confirmation before deleting the ink in Topology @private */
993   private getDeleteLinkConfirmation(d: Tick): void {
994     this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
995   }
996   /** Selected nodes @private */
997   // tslint:disable-next-line: no-any
998   private selectedNode(nodeSeleced: any, d: VNFDNODE): void {
999     const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
1000     this.deselectAllNodes();
1001     nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
1002     if (d.nodeTypeRef === 'vdu' && !alreadyIsActive) {
1003       this.vnfdPackageDetails.vdu.forEach((res: VDU) => {
1004         if (res.name === d.id) {
1005           this.showRightSideInfo = 'vduInfo';
1006           this.vduInfo = res;
1007         }
1008       });
1009     } else if (d.nodeTypeRef === 'intvl' && !alreadyIsActive) {
1010       this.vnfdPackageDetails['internal-vld'].forEach((res: InternalVLD) => {
1011         if (res.name === d.id) {
1012           this.showRightSideInfo = 'intvlInfo';
1013           this.intvlInfo = res;
1014           this.intvlInfo.shortName = res['short-name'];
1015           this.intvlInfo.ipProfileRef = res['ip-profile-ref'];
1016         }
1017       });
1018     } else if (d.nodeTypeRef === 'cp' && !alreadyIsActive) {
1019       this.vnfdPackageDetails['connection-point'].forEach((res: CONNECTIONPOINT) => {
1020         if (res.name === d.id) {
1021           this.showRightSideInfo = 'cpInfo';
1022           this.cpInfo = res;
1023         }
1024       });
1025     }
1026     else if (d.nodeTypeRef === 'intcp' && !alreadyIsActive) {
1027       this.intcpInfo = d;
1028       this.showRightSideInfo = 'intcpInfo';
1029       this.intcpInfo.shortName = d['short-name'];
1030     } else {
1031       this.showRightSideInfo = 'vnfdInfo';
1032     }
1033   }
1034   /** De-select all the selected nodes @private */
1035   private deselectAllNodes(): void {
1036     this.network.select('image').classed(this.activeNode, false);
1037     this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
1038     this.connectionPoint.select('image').classed(this.activeNode, false);
1039     this.intConnectionPoint.select('image').classed(this.activeNode, false);
1040   }
1041   /** Events handles when dragstarted @private */
1042   private dragstarted(d: COMPOSERNODES): void {
1043     d.fx = d.x;
1044     d.fy = d.y;
1045   }
1046   /** Events handles when dragged @private */
1047   private dragged(d: COMPOSERNODES): void {
1048     d.fx = d.x = d3.event.x;
1049     d.fy = d.y = d3.event.y;
1050   }
1051   /** Events handles when dragended @private */
1052   private dragended(d: COMPOSERNODES): void {
1053     if (this.forceSimulationActive) {
1054       d.fx = null;
1055       d.fy = null;
1056     } else {
1057       d.fx = d.x;
1058       d.fy = d.y;
1059       this.forceSimulationActive = false;
1060     }
1061   }
1062   /** Events handles when node double click   @private */
1063   private onNodedblClickToggleSidebar(): void {
1064     this.sideBarOpened = false;
1065   }
1066   /** Events handles when node single click   @private */
1067   private onNodeClickToggleSidebar(): void {
1068     this.sideBarOpened = true;
1069   }
1070 }