Catalog alignment
[sdc.git] / catalog-ui / src / app / models / components / component.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 'use strict';
22
23 import * as _ from "lodash";
24 import {AsdcComment, ArtifactModel, ArtifactGroupModel, IFileDownload, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance,
25     InputModel, DisplayModule, Module, IValidate, RelationshipModel, IMainCategory, RequirementsGroup, CapabilitiesGroup, AdditionalInformationModel,
26     Resource, IAppMenu, OperationModel, Service} from "../../models";
27
28 import {IComponentService} from "../../services/components/component-service";
29 import {CommonUtils} from "../../utils/common-utils";
30 import {QueueUtils} from "../../utils/functions";
31 import {ArtifactGroupType} from "../../utils/constants";
32 import {ComponentMetadata} from "../component-metadata";
33 import {Capability} from "../capability";
34 import {Requirement} from "../requirement";
35 import {Relationship} from "../graph/relationship";
36 import { PolicyInstance } from "app/models/graph/zones/policy-instance";
37 import { GroupInstance } from "../graph/zones/group-instance";
38
39
40 // import {}
41 export interface IComponent {
42
43     //---------------------------------------------- API CALLS ----------------------------------------------------//
44
45     //Component API
46     getComponent():ng.IPromise<Component>;
47     updateComponent():ng.IPromise<Component>;
48     createComponentOnServer():ng.IPromise<Component>;
49     changeLifecycleState(state:string, commentObj:AsdcComment):ng.IPromise<Component>;
50     validateName(newName:string):ng.IPromise<IValidate>;
51
52     //Artifacts API
53     addOrUpdateArtifact(artifact:ArtifactModel):ng.IPromise<ArtifactModel>;
54     deleteArtifact(artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel>;
55     downloadInstanceArtifact(artifactId:string):ng.IPromise<IFileDownload>;
56     downloadArtifact(artifactId:string):ng.IPromise<IFileDownload>;
57
58     //Property API
59     addOrUpdateProperty(property:PropertyModel):ng.IPromise<PropertyModel>;
60     deleteProperty(propertyId:string):ng.IPromise<PropertyModel>;
61
62     //Attribute API
63     deleteAttribute(attributeId:string):ng.IPromise<AttributeModel>;
64     addOrUpdateAttribute(attribute:AttributeModel):ng.IPromise<AttributeModel>;
65
66     //Modules
67     getModuleForDisplay(moduleId:string):ng.IPromise<DisplayModule>;
68     getModuleInstanceForDisplay(componentInstanceId:string, moduleId:string):ng.IPromise<DisplayModule>;
69     updateGroupMetadata(group:Module):ng.IPromise<Module>;
70
71     //---------------------------------------------- HELP FUNCTIONS ----------------------------------------------------//
72
73     getComponentSubType():string;
74     isAlreadyCertified():boolean;
75     isService():boolean;
76     isResource():boolean;
77     isComplex():boolean;
78     getAllVersionsAsSortedArray():Array<any>;
79     getStatus(sdcMenu:IAppMenu):string;
80 }
81
82
83 export abstract class Component implements IComponent {
84
85     //server data
86     public abstract:string;
87     public uniqueId:string;
88     public uuid:string;
89     public invariantUUID:string;
90     public name:string;
91     public version:string;
92     public creationDate:number;
93     public lastUpdateDate:number;
94     public description:string;
95     public lifecycleState:string;
96     public tags:Array<string>;
97     public icon:string;
98     public contactId:string;
99     public allVersions:any;
100     public creatorUserId:string;
101     public creatorFullName:string;
102     public lastUpdaterUserId:string;
103     public lastUpdaterFullName:string;
104     public componentType:string;
105     public deploymentArtifacts:ArtifactGroupModel;
106     public artifacts:ArtifactGroupModel;
107     public toscaArtifacts:ArtifactGroupModel;
108     public interfaceOperations:Array<OperationModel>;
109     public distributionStatus:string;
110     public categories:Array<IMainCategory>;
111     public categoryNormalizedName: string;
112     public subCategoryNormalizedName: string;
113     public componentInstancesProperties:PropertiesGroup;
114     public componentInstancesAttributes:AttributesGroup;
115     public componentInstancesRelations:Array<RelationshipModel>;
116     public componentInstances:Array<ComponentInstance>;
117     public inputs:Array<InputModel>;
118     public capabilities:CapabilitiesGroup;
119     public requirements:RequirementsGroup;
120     public additionalInformation:any;
121     public properties:Array<PropertyModel>;
122     public attributes:Array<AttributeModel>;
123     public highestVersion:boolean;
124     public vendorName:string;
125     public vendorRelease:string;
126     public derivedList:Array<any>;
127     public interfaces:any;
128     public normalizedName:string;
129     public systemName:string;
130     public policies:Array<PolicyInstance>;
131     public groupInstances:Array<GroupInstance>
132     public modules:Array<Module>;
133     //custom properties
134     public componentService:IComponentService;
135     public filterTerm:string;
136     public iconSprite:string;
137     public selectedInstance:ComponentInstance;
138     public mainCategory:string;
139     public subCategory:string;
140     public selectedCategory:string;
141     public showMenu:boolean;
142     public archived:boolean;
143     public vspArchived: boolean;
144     public componentMetadata: ComponentMetadata;
145
146     constructor(componentService:IComponentService, protected $q:ng.IQService, component?:Component) {
147         if (component) {
148             this.abstract = component.abstract;
149             this.uniqueId = component.uniqueId;
150             this.uuid = component.uuid;
151             this.invariantUUID = component.invariantUUID;
152             this.additionalInformation = component.additionalInformation;
153             this.artifacts = new ArtifactGroupModel(component.artifacts);
154             this.toscaArtifacts = new ArtifactGroupModel(component.toscaArtifacts);
155             this.interfaceOperations = component.interfaceOperations;
156             this.contactId = component.contactId;
157             this.categories = component.categories;
158             this.categoryNormalizedName = component.categoryNormalizedName;
159             this.subCategoryNormalizedName = component.subCategoryNormalizedName;
160             this.creatorUserId = component.creatorUserId;
161             this.creationDate = component.creationDate;
162             this.creatorFullName = component.creatorFullName;
163             this.description = component.description;
164             this.icon = component.icon;
165             this.lastUpdateDate = component.lastUpdateDate;
166             this.lastUpdaterUserId = component.lastUpdaterUserId;
167             this.lastUpdaterFullName = component.lastUpdaterFullName;
168             this.lifecycleState = component.lifecycleState;
169             this.componentInstancesRelations = CommonUtils.initComponentInstanceRelations(component.componentInstancesRelations);
170             this.componentInstancesProperties = new PropertiesGroup(component.componentInstancesProperties);
171             this.componentInstancesAttributes = new AttributesGroup(component.componentInstancesAttributes);
172             this.name = component.name;
173             this.version = component.version;
174             this.tags = [];
175             angular.copy(component.tags, this.tags);
176             this.capabilities = new CapabilitiesGroup(component.capabilities);
177             this.requirements = new RequirementsGroup(component.requirements);
178             this.allVersions = component.allVersions;
179             this.deploymentArtifacts = new ArtifactGroupModel(component.deploymentArtifacts);
180             this.componentType = component.componentType;
181             this.distributionStatus = component.distributionStatus;
182             this.highestVersion = component.highestVersion;
183             this.vendorName = component.vendorName;
184             this.vendorRelease = component.vendorRelease;
185             this.derivedList = component.derivedList;
186             this.interfaces = component.interfaces;
187             this.normalizedName = component.normalizedName;
188             this.systemName = component.systemName;
189             this.inputs = component.inputs;
190             this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
191             this.properties = CommonUtils.initProperties(component.properties, this.uniqueId);
192             this.attributes = CommonUtils.initAttributes(component.attributes, this.uniqueId);
193             this.selectedInstance = component.selectedInstance;
194             this.iconSprite = component.iconSprite;
195             this.showMenu = true;
196             this.modules = component.modules;
197             this.groupInstances = component.groupInstances;
198             this.policies = component.policies;
199             this.archived = component.archived;
200             this.vspArchived = component.vspArchived;
201         }
202
203         //custom properties
204         this.componentService = componentService;
205     }
206
207     public setUniqueId = (uniqueId:string):void => {
208         this.uniqueId = uniqueId;
209     };
210
211     //------------------------------------------ API Calls ----------------------------------------------------------------//
212     public changeLifecycleState = (state:string, commentObj:AsdcComment):ng.IPromise<Component> => {
213         let deferred = this.$q.defer<Component>();
214         let onSuccess = (componentMetadata:ComponentMetadata):void => {
215             this.setComponentMetadata(componentMetadata);
216             // this.version = componentMetadata.version;
217             this.lifecycleState = componentMetadata.lifecycleState;
218
219             deferred.resolve(this);
220         };
221         let onError = (error:any):void => {
222             deferred.reject(error);
223         };
224         this.componentService.changeLifecycleState(this, state, JSON.stringify(commentObj)).then(onSuccess, onError);
225         return deferred.promise;
226     };
227
228     public getComponent = ():ng.IPromise<Component> => {
229         return this.componentService.getComponent(this.uniqueId);
230     };
231
232     public createComponentOnServer = ():ng.IPromise<Component> => {
233         this.handleTags();
234         return this.componentService.createComponent(this);
235     };
236
237     public updateComponent = ():ng.IPromise<Component> => {
238         this.handleTags();
239         return this.componentService.updateComponent(this);
240     };
241
242     public validateName = (newName:string, subtype?:string):ng.IPromise<IValidate> => {
243         return this.componentService.validateName(newName, subtype);
244     };
245
246     public downloadArtifact = (artifactId:string):ng.IPromise<IFileDownload> => {
247         return this.componentService.downloadArtifact(this.uniqueId, artifactId);
248     };
249
250     public addOrUpdateArtifact = (artifact:ArtifactModel):ng.IPromise<ArtifactModel> => {
251         let deferred = this.$q.defer<ArtifactModel>();
252         let onSuccess = (artifactObj:ArtifactModel):void => {
253             let newArtifact = new ArtifactModel(artifactObj);
254             let artifacts = this.getArtifactsByType(artifactObj.artifactGroupType);
255             artifacts[artifactObj.artifactLabel] = newArtifact;
256             deferred.resolve(newArtifact);
257         };
258         let onError = (error:any):void => {
259             deferred.reject(error);
260         };
261         this.componentService.addOrUpdateArtifact(this.uniqueId, artifact).then(onSuccess, onError);
262         return deferred.promise;
263     };
264
265     public deleteArtifact = (artifactId:string, artifactLabel:string):ng.IPromise<ArtifactModel> => {
266         let deferred = this.$q.defer<ArtifactModel>();
267         let onSuccess = (artifactObj:ArtifactModel):void => {
268             let newArtifact = new ArtifactModel(artifactObj);
269             let artifacts = this.getArtifactsByType(artifactObj.artifactGroupType);
270             if (newArtifact.mandatory || newArtifact.serviceApi) {
271                 artifacts[newArtifact.artifactLabel] = newArtifact;
272             }
273             else {
274                 delete artifacts[artifactLabel];
275             }
276             deferred.resolve(newArtifact);
277         };
278         this.componentService.deleteArtifact(this.uniqueId, artifactId, artifactLabel).then(onSuccess);
279         return deferred.promise;
280     };
281
282     public addOrUpdateProperty = (property:PropertyModel):ng.IPromise<PropertyModel> => {
283         let deferred = this.$q.defer<PropertyModel>();
284
285         let onError = (error:any):void => {
286             deferred.reject(error);
287         };
288
289         if (!property.uniqueId) {
290             let onSuccess = (property:PropertyModel):void => {
291                 let newProperty = new PropertyModel(property);
292                 this.properties.push(newProperty);
293                 deferred.resolve(newProperty);
294             };
295             this.componentService.addProperty(this.uniqueId, property).then(onSuccess, onError);
296         }
297         else {
298             let onSuccess = (newProperty:PropertyModel):void => {
299                 // find exist instance property in parent component for update the new value ( find bu uniqueId )
300                 let existProperty:PropertyModel = <PropertyModel>_.find(this.properties, {uniqueId: newProperty.uniqueId});
301                 let propertyIndex = this.properties.indexOf(existProperty);
302                 this.properties[propertyIndex] = newProperty;
303                 deferred.resolve(newProperty);
304             };
305             this.componentService.updateProperty(this.uniqueId, property).then(onSuccess, onError);
306         }
307         return deferred.promise;
308     };
309
310     public addOrUpdateAttribute = (attribute:AttributeModel):ng.IPromise<AttributeModel> => {
311         let deferred = this.$q.defer<AttributeModel>();
312
313         let onError = (error:any):void => {
314             deferred.reject(error);
315         };
316
317         if (!attribute.uniqueId) {
318             let onSuccess = (attribute:AttributeModel):void => {
319                 let newAttribute = new AttributeModel(attribute);
320                 this.attributes.push(newAttribute);
321                 deferred.resolve(newAttribute);
322             };
323             this.componentService.addAttribute(this.uniqueId, attribute).then(onSuccess, onError);
324         }
325         else {
326             let onSuccess = (newAttribute:AttributeModel):void => {
327                 let existAttribute:AttributeModel = <AttributeModel>_.find(this.attributes, {uniqueId: newAttribute.uniqueId});
328                 let attributeIndex = this.attributes.indexOf(existAttribute);
329                 newAttribute.readonly = this.uniqueId != newAttribute.parentUniqueId;
330                 this.attributes[attributeIndex] = newAttribute;
331                 deferred.resolve(newAttribute);
332             };
333             this.componentService.updateAttribute(this.uniqueId, attribute).then(onSuccess, onError);
334         }
335         return deferred.promise;
336     };
337
338     public deleteProperty = (propertyId:string):ng.IPromise<PropertyModel> => {
339         let deferred = this.$q.defer<PropertyModel>();
340         let onSuccess = ():void => {
341             console.log("Property deleted");
342             delete _.remove(this.properties, {uniqueId: propertyId})[0];
343             deferred.resolve();
344         };
345         let onFailed = ():void => {
346             console.log("Failed to delete property");
347             deferred.reject();
348         };
349         this.componentService.deleteProperty(this.uniqueId, propertyId).then(onSuccess, onFailed);
350         return deferred.promise;
351     };
352
353     public deleteAttribute = (attributeId:string):ng.IPromise<AttributeModel> => {
354         let deferred = this.$q.defer<AttributeModel>();
355         let onSuccess = ():void => {
356             console.log("Attribute deleted");
357             delete _.remove(this.attributes, {uniqueId: attributeId})[0];
358         };
359         let onFailed = ():void => {
360             console.log("Failed to delete attribute");
361         };
362         this.componentService.deleteAttribute(this.uniqueId, attributeId).then(onSuccess, onFailed);
363         return deferred.promise;
364     };
365
366     public downloadInstanceArtifact = (artifactId:string):ng.IPromise<IFileDownload> => {
367         return this.componentService.downloadInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifactId);
368     };
369
370     public getModuleForDisplay = (moduleId:string):ng.IPromise<DisplayModule> => {
371
372         let deferred = this.$q.defer<DisplayModule>();
373         let onSuccess = (response:DisplayModule):void => {
374             deferred.resolve(response);
375         };
376         let onFailed = (error:any):void => {
377             deferred.reject(error);
378         };
379         this.componentService.getModuleForDisplay(this.uniqueId, moduleId).then(onSuccess, onFailed);
380         return deferred.promise;
381     };
382
383     public getModuleInstanceForDisplay = (componentInstanceId:string, moduleId:string):ng.IPromise<DisplayModule> => {
384
385         let deferred = this.$q.defer<DisplayModule>();
386         let onSuccess = (response:DisplayModule):void => {
387             deferred.resolve(response);
388         };
389         let onFailed = (error:any):void => {
390             deferred.reject(error);
391         };
392         this.componentService.getComponentInstanceModule(this.uniqueId, componentInstanceId, moduleId).then(onSuccess, onFailed);
393         return deferred.promise;
394     };
395
396     public updateGroupMetadata = (module:Module):ng.IPromise<Module> => {
397
398         let deferred = this.$q.defer<Module>();
399
400         let onSuccess = (updatedModule:Module):void => {
401             let groupIndex:number = _.indexOf(this.modules, _.find(this.modules, (module:Module) => {
402                 return module.uniqueId === updatedModule.uniqueId;
403             }));
404
405             if (groupIndex !== -1) {
406                 this.modules[groupIndex] = updatedModule;
407             }
408             deferred.resolve(updatedModule);
409         };
410         let onFailed = (error:any):void => {
411             deferred.reject(error);
412         };
413
414         this.componentService.updateGroupMetadata(this.uniqueId, module).then(onSuccess, onFailed);
415
416         return deferred.promise;
417     };
418
419     //------------------------------------------ Help Functions ----------------------------------------------------------------//
420
421     public isService = ():boolean => {
422         return this instanceof Service;
423     };
424
425     public isResource = ():boolean => {
426         return this instanceof Resource;
427     };
428
429     public getComponentSubType = ():string => {
430         return this.componentType;
431     };
432
433     public isAlreadyCertified = ():boolean => {
434         return parseInt(this.version) >= 1;
435     };
436
437     public isComplex = ():boolean => {
438         return true;
439     };
440
441     //sort string version value from hash to sorted version (i.e 1.9 before 1.11)
442     private sortVersions = (v1:string, v2:string):number => {
443         let ver1 = v1.split('.');
444         let ver2 = v2.split('.');
445         let diff = parseInt(_.first(ver1)) - parseInt(_.first(ver2));
446         if (!diff) {
447             return parseInt(_.last(ver1)) - parseInt(_.last(ver2));
448         }
449         return diff;
450     };
451
452     public getAllVersionsAsSortedArray = ():Array<any> => {
453         let res = [];
454         if (this.allVersions) {
455             let keys = Object.keys(this.allVersions).sort(this.sortVersions);
456             _.forEach(keys, (key)=> {
457                 res.push({
458                     versionNumber: key,
459                     versionId: this.allVersions[key]
460                 })
461             });
462         }
463         return res;
464     };
465
466     public isLatestVersion = ():boolean => {
467         if (this.allVersions) {
468             return this.version === _.last(Object.keys(this.allVersions).sort(this.sortVersions));
469         } else {
470             return true;
471         }
472
473     };
474
475
476     public handleTags = ():void => {
477         let isContainTag = _.find(this.tags, (tag)=> {
478             return tag === this.name;
479         });
480         if (!isContainTag) {
481             this.tags.push(this.name);
482         }
483     };
484
485     public getArtifactsByType = (artifactGroupType:string):ArtifactGroupModel => {
486         switch (artifactGroupType) {
487             case ArtifactGroupType.DEPLOYMENT:
488                 return this.deploymentArtifacts;
489             case ArtifactGroupType.INFORMATION:
490                 return this.artifacts;
491         }
492     };
493
494     public getStatus = (sdcMenu:IAppMenu):string => {
495         let status:string = sdcMenu.LifeCycleStatuses[this.lifecycleState].text;
496         if (this.lifecycleState == "CERTIFIED" && sdcMenu.DistributionStatuses[this.distributionStatus]) {
497             status = sdcMenu.DistributionStatuses[this.distributionStatus].text;
498         }
499         return status;
500     };
501
502     public abstract setComponentDisplayData():void;
503     public abstract getTypeUrl():string;
504
505     public setComponentMetadata(componentMetadata: ComponentMetadata) {
506         this.abstract = componentMetadata.abstract;
507         this.uniqueId = componentMetadata.uniqueId;
508         this.uuid = componentMetadata.uuid;
509         this.invariantUUID = componentMetadata.invariantUUID;
510         this.contactId = componentMetadata.contactId;
511         this.categories = componentMetadata.categories;
512         this.creatorUserId = componentMetadata.creatorUserId;
513         this.creationDate = componentMetadata.creationDate;
514         this.creatorFullName = componentMetadata.creatorFullName;
515         this.description = componentMetadata.description;
516         this.icon = componentMetadata.icon;
517         this.lastUpdateDate = componentMetadata.lastUpdateDate;
518         this.lastUpdaterUserId = componentMetadata.lastUpdaterUserId;
519         this.lastUpdaterFullName = componentMetadata.lastUpdaterFullName;
520         this.lifecycleState = componentMetadata.lifecycleState;
521         this.name = componentMetadata.name;
522         this.version = componentMetadata.version;
523         this.tags = angular.copy(componentMetadata.tags, this.tags);
524         this.allVersions = componentMetadata.allVersions;
525         this.componentType = componentMetadata.componentType;
526         this.distributionStatus = componentMetadata.distributionStatus;
527         this.highestVersion = componentMetadata.highestVersion;
528         this.vendorName = componentMetadata.vendorName;
529         this.vendorRelease = componentMetadata.vendorRelease;
530         this.derivedList = componentMetadata.derivedList;
531         this.normalizedName = componentMetadata.normalizedName;
532         this.systemName = componentMetadata.systemName;
533         this.categories = componentMetadata.categories;
534         this.archived = componentMetadata.archived || false;
535         this.vspArchived = componentMetadata.vspArchived;
536         this.componentMetadata = componentMetadata;
537     }
538
539     public toJSON = ():any => {
540         let temp = angular.copy(this);
541         temp.componentService = undefined;
542         temp.filterTerm = undefined;
543         temp.iconSprite = undefined;
544         temp.mainCategory = undefined;
545         temp.subCategory = undefined;
546         temp.selectedInstance = undefined;
547         temp.showMenu = undefined;
548         temp.$q = undefined;
549         temp.selectedCategory = undefined;
550         temp.modules = undefined
551         temp.groupInstances = undefined;
552         temp.policies = undefined;
553         return temp;
554     };
555 }
556