merge from ecomp a88f0072 - Modern UI
[vid.git] / vid-webpack-master / src / app / drawingBoard / service-planning / duplicate / duplicate.service.ts
1 import { Injectable } from '@angular/core';
2 import { ITreeNode } from 'angular-tree-component/dist/defs/api';
3 import { AppState } from '../../../shared/store/reducers';
4 import { LogService } from '../../../shared/utils/log/log.service';
5 import { NgRedux } from '@angular-redux/store';
6 import {VnfInstance} from "../../../shared/models/vnfInstance";
7 import {VfModuleMap} from "../../../shared/models/vfModulesMap";
8 import * as _ from "lodash";
9 import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
10 import {TypeNodeInformation} from "../typeNodeInformation.model";
11 import { SdcUiServices} from "onap-ui-angular";
12 import { SdcUiCommon} from "onap-ui-angular";
13 import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions";
14 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
15
16 @Injectable()
17 export class DuplicateService {
18
19   constructor(private _logService : LogService,  private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
20     this.modalService = modalService;
21   }
22
23   numberOfDuplicates:number;
24   setNumberOfDuplicates(numberOfDuplicates: number) {
25     this.numberOfDuplicates = numberOfDuplicates;
26   }
27
28   currentInstanceId: string = null;
29   currentServiceId: string = null;
30   maxNumberOfDuplicate: number = 0;
31   storeKey: string = null;
32   padding = '0000';
33   modalService: SdcUiServices.ModalService;
34   store : NgRedux<AppState>;
35   existingNames : {[key: string] : any};
36   currentNode : ITreeNode = null;
37
38
39
40   canDuplicate(node: ITreeNode): boolean {
41     let reduxState = <AppState>JSON.parse(sessionStorage.getItem('reduxState'));
42     return reduxState.global.flags['FLAG_DUPLICATE_VNF'] && (node.data.type === 'VF' || node.data.type === 'VL');
43   }
44
45   isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId : string): boolean {
46     if(!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])){
47       if(this.hasMissingData(node)) return false;
48       const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
49       const max : number = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties['max_instances'] || 1;
50       const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId];
51
52       return max - currentExisting > 0;
53     }else {
54       return false;
55     }
56   }
57
58   hasMissingData(node : ITreeNode): boolean {
59     if(!_.isNil(node)){
60       if(node.data.missingData) return true;
61       if(!_.isNil(node.data.children)){
62         for(let child of node.data.children) {
63           if(child.missingData){
64             return true;
65           }
66         }
67       }
68
69     }
70     return false;
71   }
72
73   getRemainsInstance(modelId : string, modelName : string, serviceId : string, store: NgRedux<AppState>, node : ITreeNode) : number {
74     const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
75     const properties  = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
76     const currentExisting : number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
77     return (!_.isNil(properties) && !_.isNil(properties['max_instances'])) ? properties['max_instances'] - currentExisting : null;
78   }
79
80
81
82   openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey : string, numberOfDuplicate: number, _store : NgRedux<AppState>, node: ITreeNode): IModalConfig {
83     this.currentInstanceId = currentId;
84     this.currentServiceId = currentServiceId;
85     this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node);
86     this.storeKey = storeKey;
87     this.store = _store;
88     this.currentNode = node;
89
90
91     return  {
92       size: SdcUiCommon.ModalSize.medium,
93       title: 'Duplicate Node',
94       type: SdcUiCommon.ModalType.custom,
95       buttons: [
96         {text: 'Duplicate', callback: this.duplicate.bind(this, this.currentNode), closeModal: true},
97         {text: 'Cancel', closeModal: true}
98       ]
99     };
100   }
101
102   duplicate(node : ITreeNode): void {
103     const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
104     this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames;
105     const toClone  = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
106     let newObjects = {};
107     for(let i = 0; i < this.numberOfDuplicates; i++) {
108       const uniqueStoreKey = this.generateUniqueStoreKey(this.currentServiceId, this.currentInstanceId, this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName], newObjects);
109       const clone = this.cloneVnf(toClone, this.currentInstanceId);
110       newObjects[uniqueStoreKey] = clone;
111     }
112     this.store.dispatch(duplicateBulkInstances(this.currentServiceId, newObjects, this.existingNames, node));
113     this.store.dispatch(changeInstanceCounter(toClone.modelInfo.modelUniqueId, this.currentServiceId, this.numberOfDuplicates, node));
114     this._logService.info("Duplicate " + this.storeKey + " serviceId: " + this.currentServiceId + "number of duplicate: " + this.numberOfDuplicates, toClone);
115   }
116
117
118   cloneVnf(vnf : VnfInstance, originalName: string): VnfInstance {
119     let newUniqueVnf : VnfInstance = _.cloneDeep(vnf);
120
121     newUniqueVnf.originalName = originalName;
122     newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById();
123     if (!_.isNil(vnf.instanceName)){
124       newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName);
125     }
126
127     for (let vf_module_model_name in  vnf.vfModules) {
128       const vfModuleModel: VfModuleMap = vnf.vfModules[vf_module_model_name];
129       for (let vfModule in vfModuleModel) {
130         newUniqueVnf.vfModules[vf_module_model_name][vfModule].trackById = DefaultDataGeneratorService.createRandomTrackById();
131         if (!_.isNil(vfModuleModel[vfModule].instanceName)){
132           newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName);
133         }
134         if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)){
135           newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName);
136         }
137       }
138     }
139     return newUniqueVnf;
140   }
141
142   ensureUniqueNameOrGenerateOne(instanceName){
143     let uniqueInstanceName = instanceName;
144     if (this.isAlreadyExists(instanceName, this.existingNames)) {
145       uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames);
146       this.existingNames[uniqueInstanceName.toLowerCase()] = "";
147     }
148     return uniqueInstanceName;
149   }
150
151
152   isAlreadyExists(name : string, existingNames : {[key: string] : any}){
153     return _.has(existingNames, name.toLowerCase());
154   }
155
156   generateNextUniqueName(name : string, existingNames : {[key: string] : any})  :string{
157     let suffix = "000";
158     let counter = 1;
159     if (name.match(/^.*_[\d]{3}$/)){
160       name = name.substring(0, name.length - 4);
161     }
162
163     while(true){
164       let paddingNumber : string = this.getNumberAsPaddingString(counter, suffix);
165       let candidateUniqueName = name + '_' + paddingNumber;
166       if(!this.isAlreadyExists(candidateUniqueName, existingNames)){
167         return candidateUniqueName;
168       }
169       counter++;
170     }
171   }
172
173   generateUniqueStoreKey(serviceId : string, objectName : string, existing : any, newObjects: any) : string {
174     let counter = 1;
175     while(true){
176       let paddingNumber : string = this.getNumberAsPaddingString(counter, this.padding);
177       const name = objectName + ':' + paddingNumber;
178       if(_.isNil(existing[name]) && _.isNil(newObjects[name])){
179         return name;
180       }
181       counter++;
182     }
183   }
184
185   getNumberAsPaddingString(val: number, padding: string): string {
186     const str = "" + val;
187     return padding.substring(0, padding.length - str.length) + str;
188   }
189 }