aboutsummaryrefslogtreecommitdiffstats
path: root/appc-dg/appc-dg-shared/appc-dg-dependency-model/src/main/java/org/openecomp/appc/dg/flowbuilder/impl/ForwardFlowStrategy.java
blob: 486e942a77544f311e0a28e97e04c002fc0754b0 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*-
 * ============LICENSE_START=======================================================
 * openECOMP : APP-C
 * ================================================================================
 * 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.
 * ============LICENSE_END=========================================================
 */

package org.openecomp.appc.dg.flowbuilder.impl;

import java.util.*;

import org.openecomp.appc.dg.flowbuilder.exception.InvalidDependencyModel;
import org.openecomp.appc.domainmodel.Vnfc;


public class ForwardFlowStrategy extends AbstractFlowStrategy {
    @Override
    protected List<List<Vnfc>> orderDependencies() {
        ArrayList<List<Vnfc>> arrayList = new ArrayList<>();

        Queue<Vnfc> queue1 = new LinkedList();
        Set<Vnfc> queue2 = new LinkedHashSet<>();

        Set<Vnfc> uniqueElementSet = new HashSet<>();
        Set<Vnfc> duplicateElementSet = new HashSet<>();

        // identifying independent nodes in queue1
        for(int rowIndex=0;rowIndex<graph.getSize();rowIndex++){
            Integer sum = 0;
            for(int colIndex=0;colIndex<graph.getSize();colIndex++){
                sum+= graph.getDependencyMatrix()[rowIndex][colIndex];
            }
            if(sum==0){
                Vnfc vnfc = graph.getVertexList().get(rowIndex);
                queue1.add(vnfc);
            }
        }
        if(queue1.isEmpty()){
            throw new InvalidDependencyModel("There seems to be no Root/Independent node for Vnfc dependencies");
        }
        arrayList.add((List<Vnfc>)queue1);
        queue1 = new LinkedList<>(queue1);

        boolean flag = true;

        while(flag){
            // iterating over queue1 and for each node in it finding all dependent nodes and putting them on queue2
            while(!queue1.isEmpty()){
                Vnfc listItem = queue1.remove();
                Integer colIndex = graph.getIndex(listItem);
                for(Integer index =0;index<graph.getSize();index++){
                    Integer value = graph.getDependencyMatrix()[index][colIndex];
                    if(value ==1){
                        Vnfc vnfc = graph.getVertexList().get(index);
                        queue2.add(vnfc);
                    }
                }
            }
            for(Vnfc vnfc:queue2){
                if(!uniqueElementSet.add(vnfc)){
                    duplicateElementSet.add(vnfc);
                }
            }
            if(queue2.isEmpty()){
                flag= false; // empty queue2 indicates that all leaf nodes have been identified, i.e. stop the iteration
            }
            else{
                arrayList.add(new ArrayList<Vnfc>(queue2));
                if(arrayList.size()>graph.getSize()){
                    // dependency list cannot be larger than total number of nodes
                    // if it happens indicates cycle in the dependency
                    throw new InvalidDependencyModel("Cycle detected in the VNFC dependencies");
                }
                queue1.addAll(queue2);
                queue2 = new LinkedHashSet<>();
            }
        }
        // If any node depends on multiple nodes present in different execution sequence,
        // its execution should happen on the higher order, removing its presence on lower execution sequence
        if(!duplicateElementSet.isEmpty()){
            for(Vnfc vnfc:duplicateElementSet){
                boolean firstOccurrence= true;
                for(int i=arrayList.size()-1;i>=0;i--){
                    List<Vnfc> list = arrayList.get(i);
                    if(list.contains(vnfc)){
                        if(firstOccurrence){
                            firstOccurrence =false;
                            continue;
                        }
                        else{
                            list.remove(vnfc);
                        }
                    }

                }
            }
        }
        return  arrayList;
    }
}