summaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js
blob: 8d5aaf864e6067ccd65b3e8166cdb7dab954b2c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*!
 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

import DirectedGraph from 'nfvo-utils/DirectedGraph.js';

function findCycles(
    graph,
    node,
    id,
    visited = {},
    visitedConnections = {},
    recursionStack = {},
    connectionsWithCycle = {}
) {
    visited[node] = true;
    recursionStack[node] = true;
    if (id) {
        visitedConnections[id] = true;
    }
    for (let edge of graph.getEdges(node)) {
        if (!visited[edge.target]) {
            findCycles(
                graph,
                edge.target,
                edge.id,
                visited,
                visitedConnections,
                recursionStack,
                connectionsWithCycle
            );
        } else if (recursionStack[edge.target]) {
            visitedConnections[edge.id] = true;
            for (let connection in visitedConnections) {
                connectionsWithCycle[connection] = true;
            }
        }
    }
    recursionStack[node] = false;
    return {
        visitedNodes: visited,
        connectionsWithCycle: connectionsWithCycle
    };
}

export function checkCyclesAndMarkDependencies(dependenciesList) {
    let overallVisitedNodes = {};
    let overallConnectionsWithCycles = {};

    let g = new DirectedGraph();
    for (let dependency of dependenciesList) {
        if (dependency.sourceId !== null && dependency.targetId !== null) {
            g.addEdge(dependency.sourceId, dependency.targetId, {
                id: dependency.id
            });
        }
    }

    for (let node in g.nodes) {
        if (!overallVisitedNodes.node) {
            let { visitedNodes, connectionsWithCycle } = findCycles(
                g,
                node,
                undefined
            );
            overallVisitedNodes = { ...overallVisitedNodes, ...visitedNodes };
            overallConnectionsWithCycles = {
                ...overallConnectionsWithCycles,
                ...connectionsWithCycle
            };
        }
    }
    return dependenciesList.map(dependency => ({
        ...dependency,
        hasCycle:
            dependency.sourceId && dependency.targetId
                ? overallConnectionsWithCycles.hasOwnProperty(dependency.id)
                : undefined
    }));
}
">module => ({ ...module, name: module.name || module.yaml.substring(0, module.yaml.lastIndexOf('.')) })) }; case actionTypes.ARTIFACT_LIST_CHANGE: return { ...state, artifacts: action.data.artifacts, unassigned: syncUnassignedFilesWithArtifactsChanges( state.unassigned, action.data.artifacts, state.artifacts ) }; case actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS: return { ...state, artifacts: [...state.artifacts, ...state.unassigned], unassigned: [] }; case actionTypes.ADD_ALL_ARTIFACTS_TO_UNASSIGNED: return { ...state, artifacts: [], unassigned: [...state.unassigned, ...state.artifacts] }; case actionTypes.ADD_MODULE: return { ...state, modules: state.modules.concat({ ...emptyModule(action.data.isBase, state.modules.length) }) }; case actionTypes.REMOVE_MODULE: const moduleIndexToDelete = findModuleIndexByName( state.modules, action.data.moduleName ); let unassigned = addDeletedModuleFilesToUnassigned( state.unassigned, state.modules[moduleIndexToDelete] ); return { ...state, unassigned, modules: [ ...state.modules.slice(0, moduleIndexToDelete), ...state.modules.slice(moduleIndexToDelete + 1) ] }; case actionTypes.RENAME_MODULE: const indexToRename = findModuleIndexByName( state.modules, action.data.oldName ); let moduleToRename = state.modules[indexToRename]; moduleToRename.name = action.data.newName; return { ...state, modules: [ ...state.modules.slice(0, indexToRename), moduleToRename, ...state.modules.slice(indexToRename + 1) ] }; case actionTypes.FILE_ASSIGN_CHANGED: let { module, value: { value }, type } = action.data; const moduleIndexToModify = findModuleIndexByName( state.modules, module.name ); let moduleToModify = state.modules[moduleIndexToModify]; let dumpedFile = moduleToModify[type]; if (dumpedFile !== value) { if (value) { moduleToModify[type] = value; } else { delete moduleToModify[type]; } const newUnassignedList = dumpedFile ? [ ...state.unassigned.filter(file => file !== value), dumpedFile ] : state.unassigned.filter(file => file !== value); return { ...state, modules: [ ...state.modules.slice(0, moduleIndexToModify), moduleToModify, ...state.modules.slice(moduleIndexToModify + 1) ], unassigned: newUnassignedList }; } else { return state; } default: return state; } };