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