Keyboard Shortcut for copy&Paste and delete
[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 {
25     AsdcComment, ArtifactModel, ArtifactGroupModel, IFileDownload, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance,
26     InputModel, DisplayModule, Module, IValidate, RelationshipModel, IMainCategory, RequirementsGroup, CapabilitiesGroup, AdditionalInformationModel,
27     Resource, IAppMenu, OperationModel, Service
28 } from "../../models";
29
30 import { IComponentService } from "../../services/components/component-service";
31 import { CommonUtils } from "../../utils/common-utils";
32 import { QueueUtils } from "../../utils/functions";
33 import { ArtifactGroupType } from "../../utils/constants";
34 import { ComponentMetadata } from "../component-metadata";
35 import { Capability } from "../capability";
36 import { Requirement } from "../requirement";
37 import { Relationship } from "../graph/relationship";
38 import { PolicyInstance } from "app/models/graph/zones/policy-instance";
39 import { GroupInstance } from "../graph/zones/group-instance";
40
41
42 // import {}
43 export interface IComponent {
44
45     //---------------------------------------------- API CALLS ----------------------------------------------------//
46
47     //Component API
48     getComponent(): ng.IPromise<Component>;
49     updateComponent(): ng.IPromise<Component>;
50     createComponentOnServer(): ng.IPromise<Component>;
51     changeLifecycleState(state: string, commentObj: AsdcComment): ng.IPromise<Component>;
52     validateName(newName: string): ng.IPromise<IValidate>;
53     updateRequirementsCapabilities(): ng.IPromise<any>;
54
55     //Artifacts API
56     addOrUpdateArtifact(artifact: ArtifactModel): ng.IPromise<ArtifactModel>;
57     updateMultipleArtifacts(artifacts: Array<ArtifactModel>): ng.IPromise<any>;
58     deleteArtifact(artifactId: string, artifactLabel: string): ng.IPromise<ArtifactModel>;
59     downloadInstanceArtifact(artifactId: string): ng.IPromise<IFileDownload>;
60     downloadArtifact(artifactId: string): ng.IPromise<IFileDownload>;
61     getArtifactByGroupType(artifactGroupType: string): ng.IPromise<ArtifactGroupModel>;
62
63
64     //Property API
65     addOrUpdateProperty(property: PropertyModel): ng.IPromise<PropertyModel>;
66     deleteProperty(propertyId: string): ng.IPromise<PropertyModel>;
67     updateInstanceProperties(componentInstanceId: string, properties: PropertyModel[]): ng.IPromise<PropertyModel[]>;
68
69     //Attribute API
70     deleteAttribute(attributeId: string): ng.IPromise<AttributeModel>;
71     addOrUpdateAttribute(attribute: AttributeModel): ng.IPromise<AttributeModel>;
72     updateInstanceAttribute(attribute: AttributeModel): ng.IPromise<AttributeModel>;
73
74
75
76
77     //Component Instance API
78     createComponentInstance(componentInstance: ComponentInstance): ng.IPromise<ComponentInstance>;
79     deleteComponentInstance(componentInstanceId: string): ng.IPromise<ComponentInstance>;
80     batchDeleteComponentInstance(componentInstanceIds: Array<string>): ng.IPromise<ComponentInstance>;
81     addOrUpdateInstanceArtifact(artifact: ArtifactModel): ng.IPromise<ArtifactModel>;
82     deleteInstanceArtifact(artifactId: string, artifactLabel: string): ng.IPromise<ArtifactModel>;
83     uploadInstanceEnvFile(artifact: ArtifactModel): ng.IPromise<ArtifactModel>;
84     checkComponentInstanceVersionChange(componentUid: string): ng.IPromise<any>;
85     changeComponentInstanceVersion(componentUid: string): ng.IPromise<Component>;
86     updateComponentInstance(componentInstance: ComponentInstance): ng.IPromise<ComponentInstance>;
87     updateMultipleComponentInstances(instances: Array<ComponentInstance>): ng.IPromise<Array<ComponentInstance>>;
88
89     //Inputs API
90     getComponentInstanceInputProperties(componentInstanceId: string, inputId: string): ng.IPromise<Array<PropertyModel>>
91     getComponentInstanceProperties(componentInstanceId: string): ng.IPromise<Array<PropertyModel>>
92     getComponentInputs(componentId: string): ng.IPromise<Array<InputModel>>;
93
94     createRelation(link: RelationshipModel): ng.IPromise<RelationshipModel>;
95     deleteRelation(link: RelationshipModel): ng.IPromise<RelationshipModel>;
96     batchDeleteRelation(relations: Array<RelationshipModel>): ng.IPromise<Array<RelationshipModel>>
97
98     fetchRelation(linkId: string): ng.IPromise<RelationshipModel>;
99
100
101     //Modules
102     getModuleForDisplay(moduleId: string): ng.IPromise<DisplayModule>;
103     getModuleInstanceForDisplay(componentInstanceId: string, moduleId: string): ng.IPromise<DisplayModule>;
104     updateGroupMetadata(group: Module): ng.IPromise<Module>;
105
106
107     //---------------------------------------------- HELP FUNCTIONS ----------------------------------------------------//
108
109
110
111     getComponentSubType(): string;
112     isAlreadyCertified(): boolean;
113     isService(): boolean;
114     isResource(): boolean;
115     isComplex(): boolean;
116     getAdditionalInformation(): Array<AdditionalInformationModel>;
117     getAllVersionsAsSortedArray(): Array<any>;
118     getStatus(sdcMenu: IAppMenu): string;
119 }
120
121
122 export abstract class Component implements IComponent {
123
124     //server data
125     public abstract: string;
126     public uniqueId: string;
127     public uuid: string;
128     public invariantUUID: string;
129     public name: string;
130     public version: string;
131     public creationDate: number;
132     public lastUpdateDate: number;
133     public description: string;
134     public lifecycleState: string;
135     public tags: Array<string>;
136     public icon: string;
137     public contactId: string;
138     public allVersions: any;
139     public creatorUserId: string;
140     public creatorFullName: string;
141     public lastUpdaterUserId: string;
142     public lastUpdaterFullName: string;
143     public componentType: string;
144     public deploymentArtifacts: ArtifactGroupModel;
145     public artifacts: ArtifactGroupModel;
146     public toscaArtifacts: ArtifactGroupModel;
147     public interfaceOperations: Array<OperationModel>;
148     public distributionStatus: string;
149     public categories: Array<IMainCategory>;
150     public categoryNormalizedName: string;
151     public subCategoryNormalizedName: string;
152     public componentInstancesProperties: PropertiesGroup;
153     public componentInstancesAttributes: AttributesGroup;
154     public componentInstancesRelations: Array<RelationshipModel>;
155     public componentInstances: Array<ComponentInstance>;
156     public inputs: Array<InputModel>;
157     public capabilities: CapabilitiesGroup;
158     public requirements: RequirementsGroup;
159     public additionalInformation: any;
160     public properties: Array<PropertyModel>;
161     public attributes: Array<AttributeModel>;
162     public highestVersion: boolean;
163     public vendorName: string;
164     public vendorRelease: string;
165     public derivedList: Array<any>;
166     public interfaces: any;
167     public normalizedName: string;
168     public systemName: string;
169     public projectCode: string;
170     public policies: Array<PolicyInstance>;
171     public groupInstances: Array<GroupInstance>
172     public modules: Array<Module>;
173     //custom properties
174     public componentService: IComponentService;
175     public filterTerm: string;
176     public iconSprite: string;
177     public selectedInstance: ComponentInstance;
178     public mainCategory: string;
179     public subCategory: string;
180     public selectedCategory: string;
181     public showMenu: boolean;
182     public archived: boolean;
183     public vspArchived: boolean;
184
185     constructor(componentService: IComponentService, protected $q: ng.IQService, component?: Component) {
186         if (component) {
187             this.abstract = component.abstract;
188             this.uniqueId = component.uniqueId;
189             this.uuid = component.uuid;
190             this.invariantUUID = component.invariantUUID;
191             this.additionalInformation = component.additionalInformation;
192             this.artifacts = new ArtifactGroupModel(component.artifacts);
193             this.toscaArtifacts = new ArtifactGroupModel(component.toscaArtifacts);
194             this.interfaceOperations = component.interfaceOperations;
195             this.contactId = component.contactId;
196             this.categories = component.categories;
197             this.categoryNormalizedName = component.categoryNormalizedName;
198             this.subCategoryNormalizedName = component.subCategoryNormalizedName;
199             this.creatorUserId = component.creatorUserId;
200             this.creationDate = component.creationDate;
201             this.creatorFullName = component.creatorFullName;
202             this.description = component.description;
203             this.icon = component.icon;
204             this.lastUpdateDate = component.lastUpdateDate;
205             this.lastUpdaterUserId = component.lastUpdaterUserId;
206             this.lastUpdaterFullName = component.lastUpdaterFullName;
207             this.lifecycleState = component.lifecycleState;
208             this.componentInstancesRelations = CommonUtils.initComponentInstanceRelations(component.componentInstancesRelations);
209             this.componentInstancesProperties = new PropertiesGroup(component.componentInstancesProperties);
210             this.componentInstancesAttributes = new AttributesGroup(component.componentInstancesAttributes);
211             this.name = component.name;
212             this.version = component.version;
213             this.tags = [];
214             angular.copy(component.tags, this.tags);
215             this.capabilities = new CapabilitiesGroup(component.capabilities);
216             this.requirements = new RequirementsGroup(component.requirements);
217             this.allVersions = component.allVersions;
218             this.deploymentArtifacts = new ArtifactGroupModel(component.deploymentArtifacts);
219             this.componentType = component.componentType;
220             this.distributionStatus = component.distributionStatus;
221             this.highestVersion = component.highestVersion;
222             this.vendorName = component.vendorName;
223             this.vendorRelease = component.vendorRelease;
224             this.derivedList = component.derivedList;
225             this.interfaces = component.interfaces;
226             this.normalizedName = component.normalizedName;
227             this.systemName = component.systemName;
228             this.projectCode = component.projectCode;
229             this.inputs = component.inputs;
230             this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
231             this.properties = CommonUtils.initProperties(component.properties, this.uniqueId);
232             this.attributes = CommonUtils.initAttributes(component.attributes, this.uniqueId);
233             this.selectedInstance = component.selectedInstance;
234             this.iconSprite = component.iconSprite;
235             this.showMenu = true;
236             this.modules = component.modules;
237             this.groupInstances = component.groupInstances;
238             this.policies = component.policies;
239             this.archived = component.archived;
240             this.vspArchived = component.vspArchived;
241         }
242
243         //custom properties
244         this.componentService = componentService;
245     }
246
247     public setUniqueId = (uniqueId: string): void => {
248         this.uniqueId = uniqueId;
249     };
250
251     public setSelectedInstance = (componentInstance: ComponentInstance): void => {
252         this.selectedInstance = componentInstance;
253     };
254
255
256     //------------------------------------------ API Calls ----------------------------------------------------------------//
257     public changeLifecycleState = (state: string, commentObj: AsdcComment): ng.IPromise<Component> => {
258         let deferred = this.$q.defer<Component>();
259         let onSuccess = (componentMetadata: ComponentMetadata): void => {
260             this.setComponentMetadata(componentMetadata);
261             // this.version = componentMetadata.version;
262             this.lifecycleState = componentMetadata.lifecycleState;
263
264             deferred.resolve(this);
265         };
266         let onError = (error: any): void => {
267             deferred.reject(error);
268         };
269         this.componentService.changeLifecycleState(this, state, JSON.stringify(commentObj)).then(onSuccess, onError);
270         return deferred.promise;
271     };
272
273     public getComponent = (): ng.IPromise<Component> => {
274         return this.componentService.getComponent(this.uniqueId);
275     };
276
277     public createComponentOnServer = (): ng.IPromise<Component> => {
278         this.handleTags();
279         return this.componentService.createComponent(this);
280     };
281
282     public updateComponent = (): ng.IPromise<Component> => {
283         this.handleTags();
284         return this.componentService.updateComponent(this);
285     };
286
287     public validateName = (newName: string, subtype?: string): ng.IPromise<IValidate> => {
288         return this.componentService.validateName(newName, subtype);
289     };
290
291     public downloadArtifact = (artifactId: string): ng.IPromise<IFileDownload> => {
292         return this.componentService.downloadArtifact(this.uniqueId, artifactId);
293     };
294
295     public addOrUpdateArtifact = (artifact: ArtifactModel): ng.IPromise<ArtifactModel> => {
296         let deferred = this.$q.defer<ArtifactModel>();
297         let onSuccess = (artifactObj: ArtifactModel): void => {
298             let newArtifact = new ArtifactModel(artifactObj);
299             let artifacts = this.getArtifactsByType(artifactObj.artifactGroupType);
300             artifacts[artifactObj.artifactLabel] = newArtifact;
301             deferred.resolve(newArtifact);
302         };
303         let onError = (error: any): void => {
304             deferred.reject(error);
305         };
306         this.componentService.addOrUpdateArtifact(this.uniqueId, artifact).then(onSuccess, onError);
307         return deferred.promise;
308     };
309
310     public updateMultipleArtifacts = (artifacts: Array<ArtifactModel>): ng.IPromise<any> => {
311         let deferred = this.$q.defer();
312         let onSuccess = (response: any): void => {
313             deferred.resolve(response);
314         };
315         let onError = (error: any): void => {
316             deferred.reject(error);
317         };
318         let q = new QueueUtils(this.$q);
319
320         _.forEach(artifacts, (artifact) => {
321             q.addBlockingUIAction(() => this.addOrUpdateArtifact(artifact).then(onSuccess, onError));
322         });
323         return deferred.promise;
324     };
325
326
327     public deleteArtifact = (artifactId: string, artifactLabel: string): ng.IPromise<ArtifactModel> => {
328         let deferred = this.$q.defer<ArtifactModel>();
329         let onSuccess = (artifactObj: ArtifactModel): void => {
330             let newArtifact = new ArtifactModel(artifactObj);
331             let artifacts = this.getArtifactsByType(artifactObj.artifactGroupType);
332             if (newArtifact.mandatory || newArtifact.serviceApi) {
333                 artifacts[newArtifact.artifactLabel] = newArtifact;
334             }
335             else {
336                 delete artifacts[artifactLabel];
337             }
338             deferred.resolve(newArtifact);
339         };
340         this.componentService.deleteArtifact(this.uniqueId, artifactId, artifactLabel).then(onSuccess);
341         return deferred.promise;
342     };
343
344     public getArtifactByGroupType = (artifactGroupType: string): ng.IPromise<ArtifactGroupModel> => {
345
346         let deferred = this.$q.defer<ArtifactGroupModel>();
347         let onSuccess = (response: ArtifactGroupModel): void => {
348             deferred.resolve(response);
349         };
350         let onFailed = (error: any): void => {
351             deferred.reject(error);
352         };
353         this.componentService.getArtifactByGroupType(this.uniqueId, artifactGroupType).then(onSuccess, onFailed);
354         return deferred.promise;
355     };
356
357     public getComponentInstanceArtifactsByGroupType = (componentInstanceId: string, artifactGroupType: string): ng.IPromise<ArtifactGroupModel> => {
358
359         let deferred = this.$q.defer<ArtifactGroupModel>();
360         let onSuccess = (response: ArtifactGroupModel): void => {
361             deferred.resolve(response);
362         };
363         let onFailed = (error: any): void => {
364             deferred.reject(error);
365         };
366         this.componentService.getComponentInstanceArtifactsByGroupType(this.uniqueId, componentInstanceId, artifactGroupType).then(onSuccess, onFailed);
367         return deferred.promise;
368     };
369
370     public addOrUpdateProperty = (property: PropertyModel): ng.IPromise<PropertyModel> => {
371         let deferred = this.$q.defer<PropertyModel>();
372
373         let onError = (error: any): void => {
374             deferred.reject(error);
375         };
376
377         if (!property.uniqueId) {
378             let onSuccess = (property: PropertyModel): void => {
379                 let newProperty = new PropertyModel(property);
380                 this.properties.push(newProperty);
381                 deferred.resolve(newProperty);
382             };
383             this.componentService.addProperty(this.uniqueId, property).then(onSuccess, onError);
384         }
385         else {
386             let onSuccess = (newProperty: PropertyModel): void => {
387                 // find exist instance property in parent component for update the new value ( find bu uniqueId )
388                 let existProperty: PropertyModel = <PropertyModel>_.find(this.properties, { uniqueId: newProperty.uniqueId });
389                 let propertyIndex = this.properties.indexOf(existProperty);
390                 this.properties[propertyIndex] = newProperty;
391                 deferred.resolve(newProperty);
392             };
393             this.componentService.updateProperty(this.uniqueId, property).then(onSuccess, onError);
394         }
395         return deferred.promise;
396     };
397
398     public addOrUpdateAttribute = (attribute: AttributeModel): ng.IPromise<AttributeModel> => {
399         let deferred = this.$q.defer<AttributeModel>();
400
401         let onError = (error: any): void => {
402             deferred.reject(error);
403         };
404
405         if (!attribute.uniqueId) {
406             let onSuccess = (attribute: AttributeModel): void => {
407                 let newAttribute = new AttributeModel(attribute);
408                 this.attributes.push(newAttribute);
409                 deferred.resolve(newAttribute);
410             };
411             this.componentService.addAttribute(this.uniqueId, attribute).then(onSuccess, onError);
412         }
413         else {
414             let onSuccess = (newAttribute: AttributeModel): void => {
415                 let existAttribute: AttributeModel = <AttributeModel>_.find(this.attributes, { uniqueId: newAttribute.uniqueId });
416                 let attributeIndex = this.attributes.indexOf(existAttribute);
417                 newAttribute.readonly = this.uniqueId != newAttribute.parentUniqueId;
418                 this.attributes[attributeIndex] = newAttribute;
419                 deferred.resolve(newAttribute);
420             };
421             this.componentService.updateAttribute(this.uniqueId, attribute).then(onSuccess, onError);
422         }
423         return deferred.promise;
424     };
425
426     public deleteProperty = (propertyId: string): ng.IPromise<PropertyModel> => {
427         let deferred = this.$q.defer<PropertyModel>();
428         let onSuccess = (): void => {
429             console.log("Property deleted");
430             delete _.remove(this.properties, { uniqueId: propertyId })[0];
431             deferred.resolve();
432         };
433         let onFailed = (): void => {
434             console.log("Failed to delete property");
435             deferred.reject();
436         };
437         this.componentService.deleteProperty(this.uniqueId, propertyId).then(onSuccess, onFailed);
438         return deferred.promise;
439     };
440
441     public deleteAttribute = (attributeId: string): ng.IPromise<AttributeModel> => {
442         let deferred = this.$q.defer<AttributeModel>();
443         let onSuccess = (): void => {
444             console.log("Attribute deleted");
445             delete _.remove(this.attributes, { uniqueId: attributeId })[0];
446         };
447         let onFailed = (): void => {
448             console.log("Failed to delete attribute");
449         };
450         this.componentService.deleteAttribute(this.uniqueId, attributeId).then(onSuccess, onFailed);
451         return deferred.promise;
452     };
453
454
455     public updateInstancePropertiesSuccess = (newProperties: PropertyModel[]): void => {
456         newProperties.forEach((newProperty) => {
457             // find exist instance property in parent component for update the new value ( find bu uniqueId & path)
458             let existProperty: PropertyModel = <PropertyModel>_.find(this.componentInstancesProperties[newProperty.resourceInstanceUniqueId], {
459                 uniqueId: newProperty.uniqueId,
460                 path: newProperty.path
461             });
462             let index = this.componentInstancesProperties[newProperty.resourceInstanceUniqueId].indexOf(existProperty);
463             this.componentInstancesProperties[newProperty.resourceInstanceUniqueId][index] = newProperty;
464         });
465     }
466
467     public updateInstanceProperties = (componentInstanceId: string, properties: PropertyModel[]): ng.IPromise<PropertyModel[]> => {
468         let deferred = this.$q.defer<PropertyModel[]>();
469         let onSuccess = (newProperties: PropertyModel[]): void => {
470             this.updateInstancePropertiesSuccess(newProperties);
471             deferred.resolve(newProperties);
472         };
473         let onFailed = (error: any): void => {
474             console.log('Failed to update property value');
475             deferred.reject(error);
476         };
477         this.componentService.updateInstanceProperties(this.uniqueId, componentInstanceId, properties).then(onSuccess, onFailed);
478         return deferred.promise;
479     };
480
481     public updateInstanceAttribute = (attribute: AttributeModel): ng.IPromise<AttributeModel> => {
482         let deferred = this.$q.defer<AttributeModel>();
483         let onSuccess = (newAttribute: AttributeModel): void => {
484             let existAttribute: AttributeModel = <AttributeModel>_.find(this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId], { uniqueId: newAttribute.uniqueId });
485             let index = this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId].indexOf(existAttribute);
486             this.componentInstancesAttributes[newAttribute.resourceInstanceUniqueId][index] = newAttribute;
487             deferred.resolve(newAttribute);
488         };
489         let onFailed = (error: any): void => {
490             console.log('Failed to update attribute value');
491             deferred.reject(error);
492         };
493         this.componentService.updateInstanceAttribute(this.uniqueId, attribute).then(onSuccess, onFailed);
494         return deferred.promise;
495     };
496
497     public downloadInstanceArtifact = (artifactId: string): ng.IPromise<IFileDownload> => {
498         return this.componentService.downloadInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifactId);
499     };
500
501     public deleteInstanceArtifact = (artifactId: string, artifactLabel: string): ng.IPromise<ArtifactModel> => {
502         let deferred = this.$q.defer<ArtifactModel>();
503         let onSuccess = (artifactObj: ArtifactModel): void => {
504             let newArtifact = new ArtifactModel(artifactObj);
505             let artifacts = this.selectedInstance.deploymentArtifacts;
506             if (newArtifact.mandatory || newArtifact.serviceApi) {//?????????
507                 artifacts[newArtifact.artifactLabel] = newArtifact;
508             }
509             else {
510                 delete artifacts[artifactLabel];
511             }
512             deferred.resolve(newArtifact);
513         };
514         this.componentService.deleteInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifactId, artifactLabel).then(onSuccess);
515         return deferred.promise;
516     };
517
518     public addOrUpdateInstanceArtifact = (artifact: ArtifactModel): ng.IPromise<ArtifactModel> => {
519         let deferred = this.$q.defer<ArtifactModel>();
520         let onSuccess = (artifactObj: ArtifactModel): void => {
521             switch (artifactObj.artifactGroupType) {
522                 case ArtifactGroupType.DEPLOYMENT:
523                     this.selectedInstance.deploymentArtifacts[artifactObj.artifactLabel] = artifactObj;
524                     break;
525                 case ArtifactGroupType.INFORMATION:
526                     this.selectedInstance.artifacts[artifactObj.artifactLabel] = artifactObj;
527                     break;
528             }
529             deferred.resolve(artifactObj);
530         };
531         let onError = (error: any): void => {
532             deferred.reject(error);
533         };
534         if (artifact.uniqueId) {
535             this.componentService.updateInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
536         } else {
537             this.componentService.addInstanceArtifact(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
538         }
539         return deferred.promise;
540     };
541
542     public uploadInstanceEnvFile = (artifact: ArtifactModel): ng.IPromise<ArtifactModel> => {
543         let deferred = this.$q.defer<ArtifactModel>();
544         let onSuccess = (artifactObj: ArtifactModel): void => {
545             this.selectedInstance.deploymentArtifacts[artifactObj.artifactLabel] = artifactObj;
546             deferred.resolve(artifactObj);
547         };
548         let onError = (error: any): void => {
549             deferred.reject(error);
550         };
551         this.componentService.uploadInstanceEnvFile(this.uniqueId, this.selectedInstance.uniqueId, artifact).then(onSuccess, onError);
552         return deferred.promise;
553     };
554
555     //this function will update the instance version than the function call getComponent to update the current component and return the new instance version
556     public changeComponentInstanceVersion = (componentUid: string): ng.IPromise<Component> => {
557         let deferred = this.$q.defer<Component>();
558         let onFailed = (error: any): void => {
559             deferred.reject(error);
560         };
561         let onSuccess = (componentInstance: ComponentInstance): void => {
562             let onSuccess = (component: Component): void => {
563                 component.setSelectedInstance(componentInstance);
564                 deferred.resolve(component);
565             };
566             this.getComponent().then(onSuccess, onFailed);
567         };
568         this.componentService.changeResourceInstanceVersion(this.uniqueId, this.selectedInstance.uniqueId, componentUid).then(onSuccess, onFailed);
569         return deferred.promise;
570     };
571
572     public checkComponentInstanceVersionChange = (componentUid: string): ng.IPromise<any> => {
573         return this.componentService.checkResourceInstanceVersionChange(this.uniqueId, this.selectedInstance.uniqueId, componentUid);
574     };
575
576     public createComponentInstance = (componentInstance: ComponentInstance): ng.IPromise<ComponentInstance> => {
577         let deferred = this.$q.defer<ComponentInstance>();
578         let onSuccess = (instance: ComponentInstance): void => {
579             this.componentInstances.push(instance);
580             deferred.resolve(instance);
581         };
582         let onFailed = (error: any): void => {
583             deferred.reject(error);
584         };
585         this.componentService.createComponentInstance(this.uniqueId, componentInstance).then(onSuccess, onFailed);
586         return deferred.promise;
587     };
588
589     public updateComponentInstance = (componentInstance: ComponentInstance): ng.IPromise<ComponentInstance> => {
590         let deferred = this.$q.defer<ComponentInstance>();
591         let onSuccess = (updatedInstance: ComponentInstance): void => {
592             let componentInstance: ComponentInstance = _.find(this.componentInstances, (instance: ComponentInstance) => {
593                 return instance.uniqueId === updatedInstance.uniqueId;
594             });
595
596             let index = this.componentInstances.indexOf(componentInstance);
597             this.componentInstances[index] = componentInstance;
598             deferred.resolve(updatedInstance);
599
600         };
601         let onFailed = (error: any): void => {
602             deferred.reject(error);
603         };
604         this.componentService.updateComponentInstance(this.uniqueId, componentInstance).then(onSuccess, onFailed);
605         return deferred.promise;
606     };
607
608     public updateMultipleComponentInstances = (instances: Array<ComponentInstance>): ng.IPromise<Array<ComponentInstance>> => {
609         let deferred = this.$q.defer<Array<ComponentInstance>>();
610         let onSuccess = (updatedInstances: Array<ComponentInstance>): void => {
611             _.forEach(updatedInstances, (updatedComponentInstance) => {
612                 let componentInstance: ComponentInstance = _.find(this.componentInstances, (instance: ComponentInstance) => {
613                     return instance.uniqueId === updatedComponentInstance.uniqueId;
614                 });
615
616                 let index = this.componentInstances.indexOf(componentInstance);
617                 this.componentInstances[index] = componentInstance;
618
619             });
620             deferred.resolve(updatedInstances);
621
622         };
623         let onFailed = (error: any): void => {
624             deferred.reject(error);
625         };
626         this.componentService.updateMultipleComponentInstances(this.uniqueId, instances).then(onSuccess, onFailed);
627         return deferred.promise;
628     };
629
630     public deleteComponentInstance = (componentInstanceId: string): ng.IPromise<ComponentInstance> => {
631         let deferred = this.$q.defer<ComponentInstance>();
632         let onSuccess = (): void => {
633             let onSuccess = (component: Component): void => {
634                 this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
635                 this.componentInstancesProperties = new PropertiesGroup(component.componentInstancesProperties);
636                 this.componentInstancesAttributes = new AttributesGroup(component.componentInstancesAttributes);
637                 this.modules = component.modules;
638                 this.componentInstancesRelations = CommonUtils.initComponentInstanceRelations(component.componentInstancesRelations);
639                 deferred.resolve();
640             };
641             this.getComponent().then(onSuccess);
642         };
643         let onFailed = (error: any): void => {
644             deferred.reject(error);
645         };
646         this.componentService.deleteComponentInstance(this.uniqueId, componentInstanceId).then(onSuccess, onFailed);
647         return deferred.promise;
648     };
649
650     public batchDeleteComponentInstance = (componentInstanceIds: Array<string>): ng.IPromise<any> => {
651         let deferred = this.$q.defer();
652         let onSuccess = (res: any): void => {
653             let onSuccess = (component: Component): void => {
654                 this.componentInstances = CommonUtils.initComponentInstances(component.componentInstances);
655                 this.componentInstancesProperties = new PropertiesGroup(component.componentInstancesProperties);
656                 this.componentInstancesAttributes = new AttributesGroup(component.componentInstancesAttributes);
657                 this.modules = component.modules;
658                 this.componentInstancesRelations = CommonUtils.initComponentInstanceRelations(component.componentInstancesRelations);
659                 deferred.resolve();
660
661             };
662             this.getComponent().then(onSuccess);
663             deferred.resolve(res);
664         };
665         let onFailed = (error: any): void => {
666             deferred.reject(error);
667         };
668
669         this.componentService.batchDeleteComponentInstance(this.uniqueId, componentInstanceIds).then(onSuccess, onFailed);
670         return deferred.promise;
671
672     };
673
674
675     public syncComponentByRelation(relation: RelationshipModel) {
676         relation.relationships.forEach((rel) => {
677             if (rel.capability) {
678                 const toComponentInstance: ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.toNode);
679                 const toComponentInstanceCapability: Capability = toComponentInstance.findCapability(
680                     rel.capability.type, rel.capability.uniqueId, rel.capability.ownerId, rel.capability.name);
681                 const isCapabilityFulfilled: boolean = rel.capability.isFulfilled();
682                 if (isCapabilityFulfilled && toComponentInstanceCapability) {
683                     // if capability is fulfilled and in component, then remove it
684                     console.log('Capability is fulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
685                     toComponentInstance.capabilities[rel.capability.type].splice(
686                         toComponentInstance.capabilities[rel.capability.type].findIndex((cap) => cap === toComponentInstanceCapability), 1
687                     )
688                 } else if (!isCapabilityFulfilled && !toComponentInstanceCapability) {
689                     // if capability is unfulfilled and not in component, then add it
690                     console.log('Capability is unfulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences);
691                     toComponentInstance.capabilities[rel.capability.type].push(rel.capability);
692                 }
693             }
694             if (rel.requirement) {
695                 const fromComponentInstance: ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.fromNode);
696                 const fromComponentInstanceRequirement: Requirement = fromComponentInstance.findRequirement(
697                     rel.requirement.capability, rel.requirement.uniqueId, rel.requirement.ownerId, rel.requirement.name);
698                 const isRequirementFulfilled: boolean = rel.requirement.isFulfilled();
699                 if (isRequirementFulfilled && fromComponentInstanceRequirement) {
700                     // if requirement is fulfilled and in component, then remove it
701                     console.log('Requirement is fulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
702                     fromComponentInstance.requirements[rel.requirement.capability].splice(
703                         fromComponentInstance.requirements[rel.requirement.capability].findIndex((req) => req === fromComponentInstanceRequirement), 1
704                     )
705                 } else if (!isRequirementFulfilled && !fromComponentInstanceRequirement) {
706                     // if requirement is unfulfilled and not in component, then add it
707                     console.log('Requirement is unfulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences);
708                     fromComponentInstance.requirements[rel.requirement.capability].push(rel.requirement);
709                 }
710             }
711         });
712     }
713
714     public fetchRelation = (linkId: string): ng.IPromise<RelationshipModel> => {
715         let deferred = this.$q.defer<RelationshipModel>();
716         let onSuccess = (relation: RelationshipModel): void => {
717             this.syncComponentByRelation(relation);
718             deferred.resolve(relation);
719         };
720         let onFailed = (error: any): void => {
721             deferred.reject(error);
722         };
723         this.componentService.fetchRelation(this.uniqueId, linkId).then(onSuccess, onFailed);
724         return deferred.promise;
725     };
726
727     public createRelation = (relation: RelationshipModel): ng.IPromise<RelationshipModel> => {
728         let deferred = this.$q.defer<RelationshipModel>();
729         let onSuccess = (relation: RelationshipModel): void => {
730             console.info('Link created successfully', relation);
731             if (!this.componentInstancesRelations) {
732                 this.componentInstancesRelations = [];
733             }
734             this.componentInstancesRelations.push(new RelationshipModel(relation));
735             this.syncComponentByRelation(relation);
736             deferred.resolve(relation);
737         };
738         let onFailed = (error: any): void => {
739             console.info('Failed to create relation', error);
740             deferred.reject(error);
741         };
742         this.componentService.createRelation(this.uniqueId, relation).then(onSuccess, onFailed);
743         return deferred.promise;
744     };
745
746     private deleteRelationOnSuccess(relation: RelationshipModel) {
747         let relationToDelete = _.find(this.componentInstancesRelations, (item) => {
748             return item.fromNode === relation.fromNode && item.toNode === relation.toNode && _.some(item.relationships, (relationship) => {
749                 return angular.equals(relation.relationships[0].relation, relationship.relation);
750             });
751         });
752         let index = this.componentInstancesRelations.indexOf(relationToDelete);
753         if (relationToDelete != undefined && index > -1) {
754             if (relationToDelete.relationships.length == 1) {
755                 this.componentInstancesRelations.splice(index, 1);
756             } else {
757                 this.componentInstancesRelations[index].relationships =
758                     _.reject(this.componentInstancesRelations[index].relationships, (relationship) => {
759                         return angular.equals(relation.relationships[0].relation, relationship.relation);
760                     });
761             }
762         } else {
763             console.error("Error while deleting relation - the return delete relation from server was not found in UI")
764         }
765         this.syncComponentByRelation(relation);
766     }
767
768     public deleteRelation = (relation: RelationshipModel): ng.IPromise<RelationshipModel> => {
769         let deferred = this.$q.defer<RelationshipModel>();
770         let onSuccess = (relation: RelationshipModel): void => {
771             this.deleteRelationOnSuccess(relation);
772             deferred.resolve(relation);
773         };
774         let onFailed = (error: any): void => {
775             console.error("Failed To Delete Link");
776             deferred.reject(error);
777         };
778         this.componentService.deleteRelation(this.uniqueId, relation).then(onSuccess, onFailed);
779         return deferred.promise;
780     };
781
782     public batchDeleteRelation = (relations: Array<RelationshipModel>): ng.IPromise<Array<RelationshipModel>> => {
783         let deferred = this.$q.defer<Array<RelationshipModel>>();
784         let onSuccess = (responseRelations: Array<RelationshipModel>): void => {
785             console.log("Link Batch Deleted In Server");
786             let len = responseRelations.length;
787             for (let i = 0; i < len; i++) {
788                 this.deleteRelationOnSuccess(responseRelations[i]);
789             }
790             deferred.resolve(responseRelations);
791         };
792         let onFailed = (error: any): void => {
793             console.error("Failed to batch Delete Link");
794             deferred.reject(error);
795         };
796         this.componentService.batchDeleteRelation(this.uniqueId, relations).then(onSuccess, onFailed);
797         return deferred.promise;
798     };
799
800     public getRelationRequirementCapability(relationship: Relationship, sourceNode: ComponentInstance, targetNode: ComponentInstance): Promise<{ requirement: Requirement, capability: Capability }> {
801         // try find the requirement and capability in the source and target component instances:
802         let capability: Capability = targetNode.findCapability(undefined,
803             relationship.relation.capabilityUid,
804             relationship.relation.capabilityOwnerId,
805             relationship.relation.capability);
806         let requirement: Requirement = sourceNode.findRequirement(undefined,
807             relationship.relation.requirementUid,
808             relationship.relation.requirementOwnerId,
809             relationship.relation.requirement);
810
811         return new Promise<{ requirement: Requirement, capability: Capability }>((resolve, reject) => {
812             if (capability && requirement) {
813                 resolve({ capability, requirement });
814             }
815             else {
816                 // if requirement and/or capability is missing, then fetch the full relation with its requirement and capability:
817                 this.fetchRelation(relationship.relation.id).then((fetchedRelation) => {
818                     resolve({
819                         capability: capability || fetchedRelation.relationships[0].capability,
820                         requirement: requirement || fetchedRelation.relationships[0].requirement
821                     });
822                 }, reject);
823             }
824         });
825     }
826
827     public updateRequirementsCapabilities = (): ng.IPromise<any> => {
828         let deferred = this.$q.defer();
829         let onSuccess = (response: any): void => {
830             this.capabilities = new CapabilitiesGroup(response.capabilities);
831             this.requirements = new RequirementsGroup(response.requirements);
832             deferred.resolve(response);
833         };
834         let onFailed = (error: any): void => {
835             deferred.reject(error);
836         };
837         this.componentService.getRequirementsCapabilities(this.uniqueId).then(onSuccess, onFailed);
838         return deferred.promise;
839     };
840
841     public getModuleForDisplay = (moduleId: string): ng.IPromise<DisplayModule> => {
842
843         let deferred = this.$q.defer<DisplayModule>();
844         let onSuccess = (response: DisplayModule): void => {
845             deferred.resolve(response);
846         };
847         let onFailed = (error: any): void => {
848             deferred.reject(error);
849         };
850         this.componentService.getModuleForDisplay(this.uniqueId, moduleId).then(onSuccess, onFailed);
851         return deferred.promise;
852     };
853
854     public getModuleInstanceForDisplay = (componentInstanceId: string, moduleId: string): ng.IPromise<DisplayModule> => {
855
856         let deferred = this.$q.defer<DisplayModule>();
857         let onSuccess = (response: DisplayModule): void => {
858             deferred.resolve(response);
859         };
860         let onFailed = (error: any): void => {
861             deferred.reject(error);
862         };
863         this.componentService.getComponentInstanceModule(this.uniqueId, componentInstanceId, moduleId).then(onSuccess, onFailed);
864         return deferred.promise;
865     };
866
867
868     // this function get all instances filtered by inputs and properties (optional) - if no search string insert - this function will
869     // get all the instances of the component (in service only VF instances)
870     public getComponentInstancesFilteredByInputsAndProperties = (searchText?: string): ng.IPromise<Array<ComponentInstance>> => {
871
872         let deferred = this.$q.defer<Array<ComponentInstance>>();
873         let onSuccess = (response: Array<ComponentInstance>): void => {
874             deferred.resolve(response);
875         };
876         let onFailed = (error: any): void => {
877             deferred.reject(error);
878         };
879         this.componentService.getComponentInstancesFilteredByInputsAndProperties(this.uniqueId, searchText).then(onSuccess, onFailed);
880         return deferred.promise;
881     };
882
883
884     // get inputs for instance - Pagination function
885     public getComponentInputs = (): ng.IPromise<Array<InputModel>> => {
886
887         let deferred = this.$q.defer<Array<InputModel>>();
888         let onSuccess = (inputsRes: Array<InputModel>): void => {
889             this.inputs = inputsRes;
890             deferred.resolve(inputsRes);
891         };
892         let onFailed = (error: any): void => {
893             deferred.reject(error);
894         };
895         this.componentService.getComponentInputs(this.uniqueId).then(onSuccess, onFailed);
896         return deferred.promise;
897     };
898
899
900     // get inputs instance - Pagination function
901     public getComponentInstanceInputs = (componentInstanceId: string, originComponentUid: string): ng.IPromise<Array<InputModel>> => {
902
903         let deferred = this.$q.defer<Array<InputModel>>();
904         let onSuccess = (response: Array<InputModel>): void => {
905             deferred.resolve(response);
906         };
907         let onFailed = (error: any): void => {
908             deferred.reject(error);
909         };
910         this.componentService.getComponentInstanceInputs(this.uniqueId, componentInstanceId, originComponentUid).then(onSuccess, onFailed);
911         return deferred.promise;
912     };
913
914     // get inputs inatnce - Pagination function
915     public getComponentInstanceInputProperties = (componentInstanceId: string, inputId: string): ng.IPromise<Array<PropertyModel>> => {
916
917         let deferred = this.$q.defer<Array<PropertyModel>>();
918         let onSuccess = (response: Array<PropertyModel>): void => {
919             deferred.resolve(response);
920         };
921         let onFailed = (error: any): void => {
922             deferred.reject(error);
923         };
924         this.componentService.getComponentInstanceInputProperties(this.uniqueId, componentInstanceId, inputId).then(onSuccess, onFailed);
925         return deferred.promise;
926     };
927
928     // get inputs inatnce - Pagination function
929     public getComponentInstanceProperties = (componentInstanceId: string): ng.IPromise<Array<PropertyModel>> => {
930
931         let deferred = this.$q.defer<Array<PropertyModel>>();
932         let onSuccess = (response: Array<PropertyModel>): void => {
933             deferred.resolve(response);
934         };
935         let onFailed = (error: any): void => {
936             deferred.reject(error);
937         };
938         this.componentService.getComponentInstanceProperties(this.uniqueId, componentInstanceId).then(onSuccess, onFailed);
939         return deferred.promise;
940     };
941
942
943     public updateGroupMetadata = (module: Module): ng.IPromise<Module> => {
944
945         let deferred = this.$q.defer<Module>();
946
947         let onSuccess = (updatedModule: Module): void => {
948             let groupIndex: number = _.indexOf(this.modules, _.find(this.modules, (module: Module) => {
949                 return module.uniqueId === updatedModule.uniqueId;
950             }));
951
952             if (groupIndex !== -1) {
953                 this.modules[groupIndex] = updatedModule;
954             }
955             deferred.resolve(updatedModule);
956         };
957         let onFailed = (error: any): void => {
958             deferred.reject(error);
959         };
960
961         this.componentService.updateGroupMetadata(this.uniqueId, module).then(onSuccess, onFailed);
962
963         return deferred.promise;
964     };
965
966     //------------------------------------------ Help Functions ----------------------------------------------------------------//
967
968     public isService = (): boolean => {
969         return this instanceof Service;
970     };
971
972     public isResource = (): boolean => {
973         return this instanceof Resource;
974     };
975
976     public getComponentSubType = (): string => {
977         return this.componentType;
978     };
979
980     public isAlreadyCertified = (): boolean => {
981         return parseInt(this.version) >= 1;
982     };
983
984     public isComplex = (): boolean => {
985         return true;
986     };
987
988     //sort string version value from hash to sorted version (i.e 1.9 before 1.11)
989     private sortVersions = (v1: string, v2: string): number => {
990         let ver1 = v1.split('.');
991         let ver2 = v2.split('.');
992         let diff = parseInt(_.first(ver1)) - parseInt(_.first(ver2));
993         if (!diff) {
994             return parseInt(_.last(ver1)) - parseInt(_.last(ver2));
995         }
996         return diff;
997     };
998
999     public getAllVersionsAsSortedArray = (): Array<any> => {
1000         let res = [];
1001         if (this.allVersions) {
1002             let keys = Object.keys(this.allVersions).sort(this.sortVersions);
1003             _.forEach(keys, (key) => {
1004                 res.push({
1005                     versionNumber: key,
1006                     versionId: this.allVersions[key]
1007                 })
1008             });
1009         }
1010         return res;
1011     };
1012
1013     public isLatestVersion = (): boolean => {
1014         if (this.allVersions) {
1015             return this.version === _.last(Object.keys(this.allVersions).sort(this.sortVersions));
1016         } else {
1017             return true;
1018         }
1019
1020     };
1021
1022     public getAdditionalInformation = (): Array<AdditionalInformationModel> => {
1023         let additionalInformationObject: any = _.find(this.additionalInformation, (obj: any): boolean => {
1024             return obj.parentUniqueId == this.uniqueId;
1025         });
1026         if (additionalInformationObject) {
1027             return additionalInformationObject.parameters;
1028         }
1029         return [];
1030     };
1031
1032     public handleTags = (): void => {
1033         let isContainTag = _.find(this.tags, (tag) => {
1034             return tag === this.name;
1035         });
1036         if (!isContainTag) {
1037             this.tags.push(this.name);
1038         }
1039     };
1040
1041     public getArtifactsByType = (artifactGroupType: string): ArtifactGroupModel => {
1042         switch (artifactGroupType) {
1043             case ArtifactGroupType.DEPLOYMENT:
1044                 return this.deploymentArtifacts;
1045             case ArtifactGroupType.INFORMATION:
1046                 return this.artifacts;
1047         }
1048     };
1049
1050     public getStatus = (sdcMenu: IAppMenu): string => {
1051         let status: string = sdcMenu.LifeCycleStatuses[this.lifecycleState].text;
1052         if (this.lifecycleState == "CERTIFIED" && sdcMenu.DistributionStatuses[this.distributionStatus]) {
1053             status = sdcMenu.DistributionStatuses[this.distributionStatus].text;
1054         }
1055         return status;
1056     };
1057
1058     public pasteMenuComponentInstance = (srcComponentId: string, msg: string): ng.IPromise<string> => {
1059         let deferred = this.$q.defer<string>();
1060         let onSuccess = (response): void => {
1061             deferred.resolve(response);
1062         };
1063         let onFailed = (error: any): void => {
1064             deferred.reject(error);
1065         };
1066         this.componentService.pasteMenuComponentInstance(this.uniqueId, srcComponentId, msg).then(onSuccess, onFailed);
1067         return deferred.promise;
1068
1069     };
1070     public abstract setComponentDisplayData(): void;
1071     public abstract getTypeUrl(): string;
1072
1073     public setComponentMetadata(componentMetadata: ComponentMetadata) {
1074         this.abstract = componentMetadata.abstract;
1075         this.uniqueId = componentMetadata.uniqueId;
1076         this.uuid = componentMetadata.uuid;
1077         this.invariantUUID = componentMetadata.invariantUUID;
1078         this.contactId = componentMetadata.contactId;
1079         this.categories = componentMetadata.categories;
1080         this.creatorUserId = componentMetadata.creatorUserId;
1081         this.creationDate = componentMetadata.creationDate;
1082         this.creatorFullName = componentMetadata.creatorFullName;
1083         this.description = componentMetadata.description;
1084         this.icon = componentMetadata.icon;
1085         this.lastUpdateDate = componentMetadata.lastUpdateDate;
1086         this.lastUpdaterUserId = componentMetadata.lastUpdaterUserId;
1087         this.lastUpdaterFullName = componentMetadata.lastUpdaterFullName;
1088         this.lifecycleState = componentMetadata.lifecycleState;
1089         this.name = componentMetadata.name;
1090         this.version = componentMetadata.version;
1091         this.tags = angular.copy(componentMetadata.tags, this.tags);
1092         this.allVersions = componentMetadata.allVersions;
1093         this.componentType = componentMetadata.componentType;
1094         this.distributionStatus = componentMetadata.distributionStatus;
1095         this.highestVersion = componentMetadata.highestVersion;
1096         this.vendorName = componentMetadata.vendorName;
1097         this.vendorRelease = componentMetadata.vendorRelease;
1098         this.derivedList = componentMetadata.derivedList;
1099         this.normalizedName = componentMetadata.normalizedName;
1100         this.systemName = componentMetadata.systemName;
1101         this.projectCode = componentMetadata.projectCode;
1102         this.categories = componentMetadata.categories;
1103         this.archived = componentMetadata.archived || false;
1104         this.vspArchived = componentMetadata.vspArchived;
1105     }
1106
1107     public toJSON = (): any => {
1108         let temp = angular.copy(this);
1109         temp.componentService = undefined;
1110         temp.filterTerm = undefined;
1111         temp.iconSprite = undefined;
1112         temp.mainCategory = undefined;
1113         temp.subCategory = undefined;
1114         temp.selectedInstance = undefined;
1115         temp.showMenu = undefined;
1116         temp.$q = undefined;
1117         temp.selectedCategory = undefined;
1118         temp.modules = undefined
1119         temp.groupInstances = undefined;
1120         temp.policies = undefined;
1121         return temp;
1122     };
1123 }
1124