Changes for checkstyle 8.32
[policy/apex-pdp.git] / model / policy-model / src / main / java / org / onap / policy / apex / model / policymodel / concepts / AxStateTree.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.model.policymodel.concepts;
23
24 import java.util.ArrayList;
25 import java.util.LinkedHashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.TreeSet;
29 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
30 import org.onap.policy.common.utils.validation.Assertions;
31
32 /**
33  * The Class is used to return the tree that represents the state branches or chains in a policy. It
34  * creates a tree that holds the state fan out branches in a policy that starts from the given top
35  * state of the tree. Each branch from a state is held in a set of next states for the top state and
36  * each branch in the state tree is itself a {@link AxStateTree} instance.
37  *
38  * <p>Validation checks for recursive state use, in other words validation forbids the use of a given
39  * state more than once in a state tree.
40  */
41 public class AxStateTree implements Comparable<AxStateTree> {
42     private final AxState thisState;
43     private final Set<AxStateTree> nextStates;
44
45     /**
46      * This constructor recursively creates a state tree for the given policy starting at the given
47      * state.
48      *
49      * @param policy the policy from which to read states
50      * @param thisState the state to start state tree construction at
51      * @param referencedStateNameSet a set of state names already referenced in the tree, null for
52      *        the first recursive call
53      */
54     public AxStateTree(final AxPolicy policy, final AxState thisState, Set<AxReferenceKey> referencedStateNameSet) {
55         Assertions.argumentNotNull(policy, "policy may not be null");
56         Assertions.argumentNotNull(thisState, "thisState may not be null");
57
58         this.thisState = thisState;
59         nextStates = new TreeSet<>();
60
61         for (final AxStateOutput stateOutput : thisState.getStateOutputs().values()) {
62             final AxState nextState = policy.getStateMap().get(stateOutput.getNextState().getLocalName());
63
64             // Check for end of state branch
65             if (stateOutput.getNextState().equals(AxReferenceKey.getNullKey())) {
66                 continue;
67             }
68
69             if (referencedStateNameSet == null) {
70                 referencedStateNameSet = new LinkedHashSet<>();
71                 referencedStateNameSet.add(thisState.getKey());
72             }
73
74             // Check for state tree loops
75             if (referencedStateNameSet.contains(nextState.getKey())) {
76                 throw new PolicyRuntimeException("loop detected in state tree for policy " + policy.getId() + " state "
77                         + thisState.getKey().getLocalName() + ", next state " + nextState.getKey().getLocalName()
78                         + " referenced more than once");
79             }
80             referencedStateNameSet.add(stateOutput.getNextState());
81             nextStates.add(new AxStateTree(policy, nextState, referencedStateNameSet));
82         }
83     }
84
85     /**
86      * Gets the state for this state tree node.
87      *
88      * @return the state
89      */
90     public AxState getState() {
91         return thisState;
92     }
93
94     /**
95      * Gets the next states for this state tree node.
96      *
97      * @return the next states
98      */
99     public Set<AxStateTree> getNextStates() {
100         return nextStates;
101     }
102
103     /**
104      * Gets the list of states referenced by this state tree as a list.
105      *
106      * @return the list of states referenced
107      */
108     public List<AxState> getReferencedStateList() {
109         final List<AxState> referencedStateList = new ArrayList<>();
110
111         referencedStateList.add(thisState);
112         for (final AxStateTree nextStateTree : nextStates) {
113             referencedStateList.addAll(nextStateTree.getReferencedStateList());
114         }
115
116         return referencedStateList;
117     }
118
119     /**
120      * Gets the list of states referenced by this state tree as a set.
121      *
122      * @return the set of states referenced
123      */
124     public Set<AxState> getReferencedStateSet() {
125         final Set<AxState> referencedStateSet = new TreeSet<>();
126
127         referencedStateSet.add(thisState);
128         for (final AxStateTree nextStateTree : nextStates) {
129             referencedStateSet.addAll(nextStateTree.getReferencedStateSet());
130         }
131
132         return referencedStateSet;
133     }
134
135     /**
136      * {@inheritDoc}.
137      */
138     @Override
139     public int compareTo(final AxStateTree otherObj) {
140         Assertions.argumentNotNull(otherObj, "comparison object may not be null");
141
142         if (this == otherObj) {
143             return 0;
144         }
145
146         final AxStateTree other = otherObj;
147         if (!thisState.equals(other.thisState)) {
148             return thisState.compareTo(other.thisState);
149         }
150         if (!nextStates.equals(other.nextStates)) {
151             return (nextStates.hashCode() - other.nextStates.hashCode());
152         }
153         return 0;
154     }
155 }