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