blob: c3a5a28c0ef16938efdd6b19b4a087917b6f16b2 [file] [log] [blame]
Ittay Sternf7926712019-07-07 19:23:03 +03001import {Injectable} from '@angular/core';
2import {ITreeNode} from 'angular-tree-component/dist/defs/api';
3import {AppState} from '../../../shared/store/reducers';
4import {LogService} from '../../../shared/utils/log/log.service';
5import {NgRedux} from '@angular-redux/store';
Ittay Stern6f900cc2018-08-29 17:01:32 +03006import {VnfInstance} from "../../../shared/models/vnfInstance";
7import {VfModuleMap} from "../../../shared/models/vfModulesMap";
8import * as _ from "lodash";
9import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
10import {TypeNodeInformation} from "../typeNodeInformation.model";
Yoav Schneiderman4ef3ee72020-01-08 14:46:14 +020011import {SdcUiCommon} from "onap-ui-angular";
Ittay Stern6f900cc2018-08-29 17:01:32 +030012import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions";
13import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020014import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
15import {Utils} from "../../../shared/utils/utils";
Yoav Schneiderman7b102652019-12-30 16:27:14 +020016import {SharedTreeService} from "../objectsToTree/shared.tree.service";
Yoav Schneiderman4ef3ee72020-01-08 14:46:14 +020017import {ModalService} from "../../../shared/components/customModal/services/modal.service";
Ittay Stern6f900cc2018-08-29 17:01:32 +030018
19@Injectable()
20export class DuplicateService {
21
Yoav Schneiderman7b102652019-12-30 16:27:14 +020022 constructor(private _logService: LogService,
23 private sharedTreeService : SharedTreeService,
Yoav Schneiderman4ef3ee72020-01-08 14:46:14 +020024 private _store: NgRedux<AppState>, modalService: ModalService) {
Ittay Stern6f900cc2018-08-29 17:01:32 +030025 this.modalService = modalService;
26 }
27
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020028 numberOfDuplicates: number;
29
Ittay Stern6f900cc2018-08-29 17:01:32 +030030 setNumberOfDuplicates(numberOfDuplicates: number) {
31 this.numberOfDuplicates = numberOfDuplicates;
32 }
33
34 currentInstanceId: string = null;
35 currentServiceId: string = null;
36 maxNumberOfDuplicate: number = 0;
37 storeKey: string = null;
38 padding = '0000';
Yoav Schneiderman4ef3ee72020-01-08 14:46:14 +020039 modalService: ModalService;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020040 store: NgRedux<AppState>;
41 existingNames: { [key: string]: any };
42 currentNode: ITreeNode = null;
Ittay Stern6f900cc2018-08-29 17:01:32 +030043
44
45 canDuplicate(node: ITreeNode): boolean {
46 let reduxState = <AppState>JSON.parse(sessionStorage.getItem('reduxState'));
Ittay Sternf7926712019-07-07 19:23:03 +030047 return node.data.type === 'VF' || node.data.type === 'VL';
Ittay Stern6f900cc2018-08-29 17:01:32 +030048 }
49
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020050 isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId: string): boolean {
51 if (!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])) {
52 if (this.hasMissingData(node)) return false;
53 const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
54 const flags = FeatureFlagsService.getAllFlags(store);
Ittay Stern6f900cc2018-08-29 17:01:32 +030055
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020056 const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId];
57 const maxInstances = Utils.getMaxFirstLevel(store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties, flags);
58 if (_.isNil(maxInstances)) {
59 return true;
60 } else {
61 return maxInstances - currentExisting > 0;
62 }
63
64 } else {
Ittay Stern6f900cc2018-08-29 17:01:32 +030065 return false;
66 }
67 }
68
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020069 hasMissingData(node: ITreeNode): boolean {
70 if (!_.isNil(node)) {
71 if (node.data.missingData) return true;
72 if (!_.isNil(node.data.children)) {
73 for (let child of node.data.children) {
74 if (child.missingData) {
Ittay Stern6f900cc2018-08-29 17:01:32 +030075 return true;
76 }
77 }
78 }
79
80 }
81 return false;
82 }
83
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020084 getRemainsInstance(modelId: string, modelName: string, serviceId: string, store: NgRedux<AppState>, node: ITreeNode): number {
85 const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
86 const properties = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
87 const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
88
89 const flags = FeatureFlagsService.getAllFlags(store);
90 const maxInstances = Utils.getMaxFirstLevel(properties, flags);
91 if (_.isNil(maxInstances)) {
92 return 10;
93 } else {
94 return maxInstances - currentExisting;
95 }
Ittay Stern6f900cc2018-08-29 17:01:32 +030096 }
97
98
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +020099 openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey: string, numberOfDuplicate: number, _store: NgRedux<AppState>, node: ITreeNode): IModalConfig {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300100 this.currentInstanceId = currentId;
101 this.currentServiceId = currentServiceId;
102 this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node);
103 this.storeKey = storeKey;
104 this.store = _store;
105 this.currentNode = node;
106
107
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200108 return {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300109 size: SdcUiCommon.ModalSize.medium,
110 title: 'Duplicate Node',
111 type: SdcUiCommon.ModalType.custom,
112 buttons: [
113 {text: 'Duplicate', callback: this.duplicate.bind(this, this.currentNode), closeModal: true},
114 {text: 'Cancel', closeModal: true}
115 ]
116 };
117 }
118
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200119 duplicate(node: ITreeNode): void {
120 const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
Ittay Stern6f900cc2018-08-29 17:01:32 +0300121 this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200122 const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
Ittay Stern6f900cc2018-08-29 17:01:32 +0300123 let newObjects = {};
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200124 for (let i = 0; i < this.numberOfDuplicates; i++) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300125 const uniqueStoreKey = this.generateUniqueStoreKey(this.currentServiceId, this.currentInstanceId, this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName], newObjects);
126 const clone = this.cloneVnf(toClone, this.currentInstanceId);
127 newObjects[uniqueStoreKey] = clone;
128 }
129 this.store.dispatch(duplicateBulkInstances(this.currentServiceId, newObjects, this.existingNames, node));
Yoav Schneiderman7b102652019-12-30 16:27:14 +0200130 this.store.dispatch(changeInstanceCounter(this.sharedTreeService.modelUniqueId(toClone), this.currentServiceId, this.numberOfDuplicates, node));
Ittay Stern6f900cc2018-08-29 17:01:32 +0300131 this._logService.info("Duplicate " + this.storeKey + " serviceId: " + this.currentServiceId + "number of duplicate: " + this.numberOfDuplicates, toClone);
132 }
133
134
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200135 cloneVnf(vnf: VnfInstance, originalName: string): VnfInstance {
136 let newUniqueVnf: VnfInstance = _.cloneDeep(vnf);
Ittay Stern6f900cc2018-08-29 17:01:32 +0300137
138 newUniqueVnf.originalName = originalName;
139 newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById();
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200140 if (!_.isNil(vnf.instanceName)) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300141 newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName);
142 }
143
144 for (let vf_module_model_name in vnf.vfModules) {
145 const vfModuleModel: VfModuleMap = vnf.vfModules[vf_module_model_name];
146 for (let vfModule in vfModuleModel) {
147 newUniqueVnf.vfModules[vf_module_model_name][vfModule].trackById = DefaultDataGeneratorService.createRandomTrackById();
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200148 if (!_.isNil(vfModuleModel[vfModule].instanceName)) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300149 newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName);
150 }
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200151 if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300152 newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName);
153 }
154 }
155 }
156 return newUniqueVnf;
157 }
158
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200159 ensureUniqueNameOrGenerateOne(instanceName) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300160 let uniqueInstanceName = instanceName;
161 if (this.isAlreadyExists(instanceName, this.existingNames)) {
162 uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames);
163 this.existingNames[uniqueInstanceName.toLowerCase()] = "";
164 }
165 return uniqueInstanceName;
166 }
167
168
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200169 isAlreadyExists(name: string, existingNames: { [key: string]: any }) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300170 return _.has(existingNames, name.toLowerCase());
171 }
172
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200173 generateNextUniqueName(name: string, existingNames: { [key: string]: any }): string {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300174 let suffix = "000";
175 let counter = 1;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200176 if (name.match(/^.*_[\d]{3}$/)) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300177 name = name.substring(0, name.length - 4);
178 }
179
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200180 while (true) {
181 let paddingNumber: string = this.getNumberAsPaddingString(counter, suffix);
Ittay Stern6f900cc2018-08-29 17:01:32 +0300182 let candidateUniqueName = name + '_' + paddingNumber;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200183 if (!this.isAlreadyExists(candidateUniqueName, existingNames)) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300184 return candidateUniqueName;
185 }
186 counter++;
187 }
188 }
189
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200190 generateUniqueStoreKey(serviceId: string, objectName: string, existing: any, newObjects: any): string {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300191 let counter = 1;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200192 while (true) {
193 let paddingNumber: string = this.getNumberAsPaddingString(counter, this.padding);
Ittay Stern6f900cc2018-08-29 17:01:32 +0300194 const name = objectName + ':' + paddingNumber;
Yoav Schneiderman1f2a2942019-12-09 16:42:21 +0200195 if (_.isNil(existing[name]) && _.isNil(newObjects[name])) {
Ittay Stern6f900cc2018-08-29 17:01:32 +0300196 return name;
197 }
198 counter++;
199 }
200 }
201
202 getNumberAsPaddingString(val: number, padding: string): string {
203 const str = "" + val;
204 return padding.substring(0, padding.length - str.length) + str;
205 }
206}