merge from ecomp a88f0072 - Modern UI
[vid.git] / vid-webpack-master / src / app / drawingBoard / service-planning / objectsToTree / objectToInstanceTree / objectToInstanceTree.service.ts
1 import {Injectable} from "@angular/core";
2 import {ILevelNodeInfo} from "../models/basic.model.info";
3 import {ObjectToTreeService} from "../objectToTree.service";
4 import {DefaultDataGeneratorService} from "../../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
5 import * as _ from "lodash";
6 import {ServiceInstanceActions} from "../../../../shared/models/serviceInstanceActions";
7 import {ErrorMsgService} from "../../../../shared/components/error-msg/error-msg.service";
8 import {FeatureFlagsService, Features} from "../../../../shared/services/featureFlag/feature-flags.service";
9 import {NgRedux} from "@angular-redux/store";
10 import {AppState} from "../../../../shared/store/reducers";
11
12 @Injectable()
13 export class ObjectToInstanceTreeService {
14   constructor(private _objectToTreeService: ObjectToTreeService, private _errorMsgService: ErrorMsgService, private store: NgRedux<AppState>) {
15     this.numberOfFailed = 0;
16     this.numberOfElements = 0;
17
18   }
19
20   /** store number of failed ********  ONLY IN RETRY MODE  ******** **/
21   numberOfFailed: number = 0;
22
23   /** store number of existing elements **/
24   numberOfElements: number = 0;
25
26   /*****************************************************************
27    * return array of first level node with there child's
28    * @param serviceInstance - The service instance object from store
29    * @param serviceHierarchy - The service Hierarchy store
30    ****************************************************************/
31   convertServiceInstanceToTreeData(serviceInstance, serviceHierarchy): any[] {
32     this._errorMsgService.triggerClearError.next();
33     let nodes = [];
34     this.numberOfFailed = 0;
35     this.numberOfElements = 0;
36     let _this = this;
37     const firstLevelOptions: ILevelNodeInfo[] = _this._objectToTreeService.getFirstLevelOptions();
38     for (let option of firstLevelOptions) {
39       _.forOwn(serviceInstance[option.name], function (instance, modelName) {
40         nodes.push(_this.getNodeInstance(modelName, null, instance, serviceHierarchy, option));
41       });
42     }
43     return this.sortElementsByPosition(nodes);
44   }
45
46   /*****************************************************************
47    * should increase number of failed
48    * @param node - the current node
49    ****************************************************************/
50   increaseNumberOfFailed(node) {
51     if (node.isFailed) {
52       this.numberOfFailed++;
53       node['errors'] = !_.isNil(node['errors']) ? node['errors'] : {};
54       node['errors']["isFailed"] = true;
55       this._errorMsgService.triggerShowError.next(this._errorMsgService.getRetryErrorObject(this.numberOfFailed));
56     }
57   }
58
59   /*****************************************************************
60    * should increase number of existing elements
61    * @param node - the current node
62    ****************************************************************/
63   increaseNumberOfExcitingElements() {
64     this.numberOfElements++;
65   }
66
67   /*****************************************************************
68    * return array of first level node with there child's
69    * @param modelName
70    * @param parentModel
71    * @param instance
72    * @param serviceHierarchy - The service Hierarchy store
73    * @param option
74    * @param parentType
75    ****************************************************************/
76   getNodeInstance(modelName: string, parentModel: any, instance: any, serviceHierarchy, option: ILevelNodeInfo, parentType ?: string) {
77     const model = option.getModel(modelName, instance, serviceHierarchy);
78
79     let optionalNodes = option.createInstanceTreeNode(instance, model, parentModel, modelName);
80     this.increaseNumberOfFailed(optionalNodes);
81     this.increaseNumberOfExcitingElements();
82     let nodes: any[] = _.isArray(optionalNodes) ? optionalNodes : [optionalNodes];
83     for (let node of nodes) {
84       node = this.addingExtraDataToNode(node, modelName, parentModel, instance, serviceHierarchy, option, parentType);
85       let children = this.addNextInstanceTreeNode(instance, model, option, node, serviceHierarchy);
86       if (!_.isNil(children) && children.length > 0) {
87         node.children = this.sortElementsByPosition(children);
88       }
89       this.updateScalingPolicy(node);
90     }
91     return nodes.length === 1 ? nodes[0] : nodes;
92   }
93
94   addingExtraDataToNode(node, modelName: string, parentModel: any, instance: any, serviceHierarchy, option: ILevelNodeInfo, parentType ?: string) {
95     node.trackById = _.isNil(node.trackById) ? DefaultDataGeneratorService.createRandomTrackById() : node['trackById'];
96     node.parentType = !_.isNil(parentType) ? parentType : "";
97     node.updatePoistionFunction = option.updatePosition;
98     node.position = option.getNodePosition(instance, node.dynamicModelName);
99     node.onSelectedNode = option.onSelectedNode;
100     return node;
101   }
102
103   sortElementsByPosition(nodes: any[]): any[] {
104     if (!FeatureFlagsService.getFlagState(Features.DRAG_AND_DROP_OPERATION, this.store)) return nodes;
105     return nodes.sort((nodeA, nodeB) => {
106       return nodeA.position - nodeB.position;
107     });
108   }
109
110   /*****************************************************************
111    * return next level node with there child's
112    * @param parentInstance
113    * @param parentModel
114    * @param levelNodeInfo
115    * @param parentNode
116    * @param serviceHierarchy - The service Hierarchy store
117    ****************************************************************/
118   addNextInstanceTreeNode(parentInstance, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, serviceHierarchy): any[] {
119     if (!_.isNil(levelNodeInfo.childName)) {
120       parentNode.children = [];
121       if (!_.isNil(parentInstance[levelNodeInfo.childName])) {
122         let parentType = levelNodeInfo.type;
123         let nextLevelNodeInfo = levelNodeInfo.getNextLevelObject.apply(this);
124         Object.keys(parentInstance[levelNodeInfo.childName]).map((modelName) => {
125           let nextLevelInstance = parentInstance[levelNodeInfo.childName][modelName];
126           let nodes: any[] | any = this.getNodeInstance(modelName, parentModel, nextLevelInstance, serviceHierarchy, nextLevelNodeInfo, parentType);
127           if (_.isArray(nodes)) {
128             parentNode.children = parentNode.children.concat(nodes);
129           } else {
130             parentNode.children.push(nodes);
131           }
132         });
133         return this.sortElementsByPosition(parentNode.children);
134       }
135     }
136     return parentNode.children;
137   }
138
139
140   /************************************************************************************
141    * update instance scaling policy according to instance limit and existing children
142    * @param node
143    *********************************************************************************/
144   updateScalingPolicy(node): void {
145     node['errors'] = !_.isNil(node['errors']) ? node['errors'] : {};
146     if (!_.isNil(node['limitMembers']) && !_.isNil(node.children)) {
147       let effectiveChildren = (node.children).filter(child => [
148         ServiceInstanceActions.Create,
149         ServiceInstanceActions.None,
150         ServiceInstanceActions.Update
151       ].includes(child.action));
152
153
154       if (effectiveChildren.length > node.limitMembers) {
155         node['errors']["scalingError"] = true;
156         this._errorMsgService.triggerShowError.next(this._errorMsgService.getScalingErrorObject());
157       } else {
158         delete node['errors']["scalingError"];
159       }
160
161     }
162   }
163 }