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";
23 Requirement, CompositionCiLinkBase, CapabilitiesGroup, RequirementsGroup, Match,
24 CompositionCiNodeBase, Component, Capability
26 import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
28 * Created by obarda on 1/1/2017.
31 export class MatchCapabilitiesRequirementsUtils {
34 * Shows + icon in corner of each node passed in
35 * @param filteredNodesData
38 public highlightMatchingComponents(filteredNodesData, cy:Cy.Instance) {
39 _.each(filteredNodesData, (data:any) => {
40 let node = cy.getElementById(data.id);
41 cy.emit('showhandle', [node]);
46 * Adds opacity to each node that cannot be linked to hovered node
47 * @param filteredNodesData
50 * @param hoveredNodeData
52 public fadeNonMachingComponents(filteredNodesData, nodesData, cy:Cy.Instance, hoveredNodeData?) {
53 let fadeNodes = _.xorWith(nodesData, filteredNodesData, (node1, node2) => {
54 return node1.id === node2.id;
56 if (hoveredNodeData) {
57 _.remove(fadeNodes, hoveredNodeData);
60 _.each(fadeNodes, (node) => {
61 cy.getElementById(node.id).style({'background-image-opacity': 0.4});
67 * Resets all nodes to regular opacity
70 public resetFadedNodes(cy:Cy.Instance) {
72 cy.nodes().style({'background-image-opacity': 1});
76 private static isRequirementFulfilled(fromNodeId:string, requirement:any, links:Array<CompositionCiLinkBase>):boolean {
77 if(requirement.maxOccurrences === 'UNBOUNDED'){
80 let linksWithThisReq:Array<CompositionCiLinkBase> = _.filter(links, {
82 'fromNode': fromNodeId,
85 'requirementOwnerId': requirement.ownerId,
86 'requirement': requirement.name,
88 'type': requirement.capability
95 return linksWithThisReq.length == requirement.maxOccurrences;
98 private static isMatch(requirement:Requirement, capability:Capability):boolean {
99 if (capability.type === requirement.capability) {
100 if (requirement.node) {
101 if (_.includes(capability.capabilitySources, requirement.node)) {
111 public getMatchedRequirementsCapabilities(fromComponentInstance:ComponentInstance,
112 toComponentInstance:ComponentInstance,
113 links:Array<CompositionCiLinkBase>):Array<Match> {
114 let fromToMatches:Array<Match> = this.getMatches(fromComponentInstance.requirements,
115 toComponentInstance.capabilities,
117 fromComponentInstance.uniqueId,
118 toComponentInstance.uniqueId, true);
119 let toFromMatches:Array<Match> = this.getMatches(toComponentInstance.requirements,
120 fromComponentInstance.capabilities,
122 fromComponentInstance.uniqueId,
123 toComponentInstance.uniqueId, false);
125 return fromToMatches.concat(toFromMatches);
128 /***** REFACTORED FUNCTIONS START HERE *****/
130 public getMatches(requirements:RequirementsGroup, capabilities:CapabilitiesGroup, links:Array<CompositionCiLinkBase>,
131 fromId:string, toId:string, isFromTo: boolean):Array<Match> {
132 let matches:Array<Match> = [];
133 let unfulfilledReqs = this.getUnfulfilledRequirements(fromId, requirements, links);
134 _.forEach(unfulfilledReqs, (req)=> {
135 _.forEach(_.flatten(_.values(capabilities)), (capability:Capability)=> {
136 if (MatchCapabilitiesRequirementsUtils.isMatch(req, capability)) {
138 matches.push(new Match(req, capability, isFromTo, fromId, toId));
140 matches.push(new Match(req, capability, isFromTo, toId, fromId));
148 public getUnfulfilledRequirements = (fromNodeId:string, requirements:RequirementsGroup, links:Array<CompositionCiLinkBase>):Array<Requirement>=> {
150 let requirementArray:Array<Requirement> = [];
151 _.forEach(_.flatten(_.values(requirements)), (requirement:Requirement)=> {
152 if (requirement.name !== 'dependency' && requirement.parentName !== 'dependency' && !MatchCapabilitiesRequirementsUtils.isRequirementFulfilled(fromNodeId, requirement, links)) {
153 requirementArray.push(requirement);
156 return requirementArray;
161 * Returns true if there is a match between the capabilities and requirements that are passed in
162 * @param requirements
163 * @param capabilities
166 public containsMatch = (requirements:Array<Requirement>, capabilities:CapabilitiesGroup):boolean => {
167 return _.some(requirements, (req:Requirement)=> {
168 return _.some(_.flatten(_.values(capabilities)), (capability:Capability) => {
169 return MatchCapabilitiesRequirementsUtils.isMatch(req, capability);
175 * Returns array of nodes that can connect to the component.
176 * In order to connect, one of the following conditions must be met:
177 * 1. component has an unfulfilled requirement that matches a node's capabilities
178 * 2. node has an unfulfilled requirement that matches the component's capabilities
179 * 3. vl is passed in which has the capability to fulfill requirement from component and requirement on node.
181 public findMatchingNodes(component:Component, nodeDataArray:Array<CompositionCiNodeBase>,
182 links:Array<CompositionCiLinkBase>):Array<any> //TODO allow for VL array and TEST
184 let componentRequirements:Array<Requirement> = this.getUnfulfilledRequirements(component.uniqueId, component.requirements, links);
185 return _.filter(nodeDataArray, (node:any)=> {
186 if (node && node.componentInstance) {
188 //Check if component has an unfulfilled requirement that can be met by one of nodes's capabilities (#1)
189 if (componentRequirements.length && node.category !== 'groupCp' && this.containsMatch(componentRequirements, node.componentInstance.capabilities)) {
192 } else { //Check if node has unfulfilled requirement that can be filled by component (#2)
193 let nodeRequirements:Array<Requirement> = this.getUnfulfilledRequirements(node.componentInstance.uniqueId, node.componentInstance.requirements, links);
194 if (!nodeRequirements.length) return false;
195 if (this.containsMatch(nodeRequirements, component.capabilities)) {
204 MatchCapabilitiesRequirementsUtils.$inject = [];