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