2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 import * as _ from "lodash";
22 import {RelationshipModel, Component, ComponentInstance} from "app/models";
23 import {Dictionary} from "app/utils";
26 export interface IStructureTreeScope extends ng.IScope {
29 structureTree:StructureTree;
34 serviceRoot:ResourceInstanceNode;
36 constructor(private uniqueId:string, private resourceInstanceName:string, private resourceInstanceIcon:string, private certified:boolean) {
37 this.serviceRoot = new ResourceInstanceNode(uniqueId, resourceInstanceName, resourceInstanceIcon, certified);
42 class ResourceInstanceNode {
46 resourceInstancesList:Array<ResourceInstanceNode>;
47 isAlreadyInTree:boolean;
51 constructor(private uniqueId:string, private resourceInstanceName:string, private resourceInstanceIcon:string, certified:boolean) {
53 this.name = resourceInstanceName;
54 this.icon = resourceInstanceIcon;
55 this.resourceInstancesList = [];
56 this.isAlreadyInTree = false;
57 this.certified = certified;
61 export class StructureTreeDirective implements ng.IDirective {
71 template = ():string => {
72 return require('./structure-tree-directive.html');
75 link = (scope:IStructureTreeScope, $elem:any) => {
77 let RESOURCE_INSTANCE_LIST:string = "resourceInstancesChildesList";
78 let resourceInstanceMap:Dictionary<string, ResourceInstanceNode>;
79 let relations:Array<RelationshipModel>;
80 //************* Start Building Tree Functions *******************//
82 //remove unnecessary instances
83 let initResourceInstanceMap = ():void => {
85 resourceInstanceMap = new Dictionary<string, ResourceInstanceNode>();
87 _.forEach(scope.component.componentInstances, (resourceInstance:ComponentInstance)=> {
88 if (_.some(Object.keys(resourceInstance.capabilities), (key:string)=> {
89 return 'tosca.capabilities.container' == key.toLowerCase();
90 }) || _.some(Object.keys(resourceInstance.requirements), (key:string)=> {
91 return 'tosca.capabilities.container' == key.toLowerCase();
94 let isCertified = 0 === (parseFloat(resourceInstance.componentVersion) % 1);
95 let node:ResourceInstanceNode = new ResourceInstanceNode(resourceInstance.uniqueId,
96 resourceInstance.name,
97 resourceInstance.icon,
99 resourceInstanceMap.setValue(resourceInstance.uniqueId, node);
104 //remove unnecessary relations
105 let initRelations = ():void => {
106 relations = _.filter(scope.component.componentInstancesRelations, (relation:RelationshipModel)=> {
107 return resourceInstanceMap.containsKey(relation.fromNode) && resourceInstanceMap.containsKey(relation.toNode);
111 let buildTree = ():void => {
112 if (scope.component) {
113 scope.structureTree = new StructureTree(scope.component.uniqueId, scope.component.name, scope.component.icon, 'CERTIFIED' === scope.component.lifecycleState);
114 initResourceInstanceMap();
117 let parentNodesList = _.groupBy(relations, (node:any)=> {
118 return node.fromNode;
121 for (let parent in parentNodesList) {
122 _.forEach(parentNodesList[parent], (childNode)=> {
123 parentNodesList[parent][RESOURCE_INSTANCE_LIST] = [];
124 parentNodesList[parent][RESOURCE_INSTANCE_LIST].push(mergeAllSubtrees(childNode, parentNodesList));
128 //add the resourceInstanceList for the service root node
129 for (let parent in parentNodesList) {
130 let resourceInstanceNode:ResourceInstanceNode = resourceInstanceMap.getValue(parent);
131 resourceInstanceNode.resourceInstancesList = parentNodesList[parent];
132 resourceInstanceNode.resourceInstancesList = parentNodesList[parent][RESOURCE_INSTANCE_LIST];
133 resourceInstanceNode.isAlreadyInTree = true;
134 scope.structureTree.serviceRoot.resourceInstancesList.push(resourceInstanceNode);
137 // Add all node that have no connection to the rootNode
138 resourceInstanceMap.forEach((key:string, value:ResourceInstanceNode) => {
139 if (!value.isAlreadyInTree) {
140 scope.structureTree.serviceRoot.resourceInstancesList.push(value);
146 //this recursion is merging all the subtrees
147 let mergeAllSubtrees = (connectionData:any, parentNodesList:any):ResourceInstanceNode => {
148 let resourceInstanceNode:ResourceInstanceNode = resourceInstanceMap.getValue(connectionData.toNode);
149 resourceInstanceNode.isAlreadyInTree = true;
150 if (parentNodesList[resourceInstanceNode.id]) {
151 if (parentNodesList[resourceInstanceNode.id][RESOURCE_INSTANCE_LIST]) {
152 resourceInstanceNode.resourceInstancesList = parentNodesList[resourceInstanceNode.id][RESOURCE_INSTANCE_LIST];
155 _.forEach(parentNodesList[resourceInstanceNode.id], (children)=> {
156 resourceInstanceNode.resourceInstancesList.push(mergeAllSubtrees(children, parentNodesList));
159 delete parentNodesList[resourceInstanceNode.id];
161 return resourceInstanceNode;
163 //************* End Building Tree Functions *******************//
165 //************* Start Watchers *******************//
166 scope.$watch('component.name', ():void => {
167 if (scope.structureTree)
168 scope.structureTree.serviceRoot.name = scope.component.name;
171 scope.$watch('component.icon', ():void => {
172 if (scope.structureTree)
173 scope.structureTree.serviceRoot.icon = scope.component.icon;
176 scope.$watchCollection('component.componentInstancesRelations', ():void => {
180 scope.$watchCollection('component.componentInstances', ():void => {
184 //************* End Watchers *******************//
191 public static factory = () => {
192 return new StructureTreeDirective();
196 StructureTreeDirective.factory.$inject = [];