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} 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 import {SharedTreeService} from "../objectsToTree/shared.tree.service";
17 import {ModalService} from "../../../shared/components/customModal/services/modal.service";
20 export class DuplicateService {
22 constructor(private _logService: LogService,
23 private sharedTreeService : SharedTreeService,
24 private _store: NgRedux<AppState>, modalService: ModalService) {
25 this.modalService = modalService;
28 numberOfDuplicates: number;
30 setNumberOfDuplicates(numberOfDuplicates: number) {
31 this.numberOfDuplicates = numberOfDuplicates;
34 currentInstanceId: string = null;
35 currentServiceId: string = null;
36 maxNumberOfDuplicate: number = 0;
37 storeKey: string = null;
39 modalService: ModalService;
40 store: NgRedux<AppState>;
41 existingNames: { [key: string]: any };
42 currentNode: ITreeNode = null;
45 canDuplicate(node: ITreeNode): boolean {
46 let reduxState = <AppState>JSON.parse(sessionStorage.getItem('reduxState'));
47 return node.data.type === 'VF' || node.data.type === 'VL';
50 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);
56 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)) {
61 return maxInstances - currentExisting > 0;
69 hasMissingData(node: ITreeNode): boolean {
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) {
84 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];
89 const flags = FeatureFlagsService.getAllFlags(store);
90 const maxInstances = Utils.getMaxFirstLevel(properties, flags);
91 if (_.isNil(maxInstances)) {
94 return maxInstances - currentExisting;
99 openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey: string, numberOfDuplicate: number, _store: NgRedux<AppState>, node: ITreeNode): IModalConfig {
100 this.currentInstanceId = currentId;
101 this.currentServiceId = currentServiceId;
102 this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node);
103 this.storeKey = storeKey;
105 this.currentNode = node;
109 size: SdcUiCommon.ModalSize.medium,
110 title: 'Duplicate Node',
111 type: SdcUiCommon.ModalType.custom,
113 {text: 'Duplicate', callback: this.duplicate.bind(this, this.currentNode), closeModal: true},
114 {text: 'Cancel', closeModal: true}
119 duplicate(node: ITreeNode): void {
120 const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
121 this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames;
122 const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
124 for (let i = 0; i < this.numberOfDuplicates; i++) {
125 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;
129 this.store.dispatch(duplicateBulkInstances(this.currentServiceId, newObjects, this.existingNames, node));
130 this.store.dispatch(changeInstanceCounter(this.sharedTreeService.modelUniqueId(toClone), this.currentServiceId, this.numberOfDuplicates, node));
131 this._logService.info("Duplicate " + this.storeKey + " serviceId: " + this.currentServiceId + "number of duplicate: " + this.numberOfDuplicates, toClone);
135 cloneVnf(vnf: VnfInstance, originalName: string): VnfInstance {
136 let newUniqueVnf: VnfInstance = _.cloneDeep(vnf);
138 newUniqueVnf.originalName = originalName;
139 newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById();
140 if (!_.isNil(vnf.instanceName)) {
141 newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName);
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();
148 if (!_.isNil(vfModuleModel[vfModule].instanceName)) {
149 newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName);
151 if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)) {
152 newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName);
159 ensureUniqueNameOrGenerateOne(instanceName) {
160 let uniqueInstanceName = instanceName;
161 if (this.isAlreadyExists(instanceName, this.existingNames)) {
162 uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames);
163 this.existingNames[uniqueInstanceName.toLowerCase()] = "";
165 return uniqueInstanceName;
169 isAlreadyExists(name: string, existingNames: { [key: string]: any }) {
170 return _.has(existingNames, name.toLowerCase());
173 generateNextUniqueName(name: string, existingNames: { [key: string]: any }): string {
176 if (name.match(/^.*_[\d]{3}$/)) {
177 name = name.substring(0, name.length - 4);
181 let paddingNumber: string = this.getNumberAsPaddingString(counter, suffix);
182 let candidateUniqueName = name + '_' + paddingNumber;
183 if (!this.isAlreadyExists(candidateUniqueName, existingNames)) {
184 return candidateUniqueName;
190 generateUniqueStoreKey(serviceId: string, objectName: string, existing: any, newObjects: any): string {
193 let paddingNumber: string = this.getNumberAsPaddingString(counter, this.padding);
194 const name = objectName + ':' + paddingNumber;
195 if (_.isNil(existing[name]) && _.isNil(newObjects[name])) {
202 getNumberAsPaddingString(val: number, padding: string): string {
203 const str = "" + val;
204 return padding.substring(0, padding.length - str.length) + str;