Changes for checkstyle 8.32
[policy/apex-pdp.git] / core / core-engine / src / main / java / org / onap / policy / apex / core / engine / executor / StateMachineExecutor.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.core.engine.executor;
23
24 import java.util.Map;
25 import java.util.Properties;
26 import java.util.TreeMap;
27 import org.onap.policy.apex.context.ContextException;
28 import org.onap.policy.apex.core.engine.ExecutorParameters;
29 import org.onap.policy.apex.core.engine.context.ApexInternalContext;
30 import org.onap.policy.apex.core.engine.event.EnEvent;
31 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
32 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
33 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
34 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
35 import org.onap.policy.apex.model.policymodel.concepts.AxState;
36 import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
37
38 /**
39  * This class is the executor for a state machine built from a policy.
40  *
41  * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
42  * @author Liam Fallon (liam.fallon@ericsson.com)
43  */
44 public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> {
45     // The Apex Policy and context for this state machine
46     private AxPolicy axPolicy = null;
47     private Executor<?, ?, ?, ?> parent = null;
48     private ApexInternalContext internalContext = null;
49
50     // The list of state executors for this state machine
51     private final Map<AxReferenceKey, StateExecutor> stateExecutorMap = new TreeMap<>();
52
53     // The first executor
54     private StateExecutor firstExecutor = null;
55
56     // The next state machine executor
57     private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutor = null;
58
59     // The executor factory
60     private ExecutorFactory executorFactory = null;
61
62     /**
63      * Constructor, save the executor factory that will give us executors for task selection logic and task logic.
64      *
65      * @param executorFactory the executor factory
66      * @param owner the artifact key of the owner of this state machine
67      */
68     public StateMachineExecutor(final ExecutorFactory executorFactory, final AxArtifactKey owner) {
69         this.executorFactory = executorFactory;
70     }
71
72     /**
73      * {@inheritDoc}.
74      */
75     @Override
76     public void setContext(final Executor<?, ?, ?, ?> newParent, final AxPolicy newAxPolicy,
77             final ApexInternalContext newInternalContext) {
78         // Save the policy and context for this state machine
79         this.parent = newParent;
80         this.axPolicy = newAxPolicy;
81         this.internalContext = newInternalContext;
82
83         // Clear the first executor, setContext can be called multiple times
84         firstExecutor = null;
85
86         // Create the state executors for this state machine
87         StateExecutor lastExecutor = null;
88         for (final AxState state : axPolicy.getStateMap().values()) {
89             // Create a state executor for this state and add its context (the state)
90             final StateExecutor stateExecutor = new StateExecutor(executorFactory);
91             stateExecutor.setContext(this, state, internalContext);
92
93             // Update the next executor on the last executor
94             if (lastExecutor != null) {
95                 lastExecutor.setNext(stateExecutor);
96             }
97             lastExecutor = stateExecutor;
98
99             // Add the state executor to the executor list
100             stateExecutorMap.put(state.getKey(), stateExecutor);
101
102             // Set the first executor if it is not set
103             if (state.getKey().getLocalName().equals(axPolicy.getFirstState())) {
104                 firstExecutor = stateExecutor;
105             }
106         }
107     }
108
109     /**
110      * {@inheritDoc}.
111      */
112     @Override
113     public void prepare() throws StateMachineException {
114         for (final StateExecutor stateExecutor : stateExecutorMap.values()) {
115             stateExecutor.prepare();
116         }
117     }
118
119     /**
120      * {@inheritDoc}.
121      */
122     @Override
123     public EnEvent execute(final long executionId, final Properties executionProperties, final EnEvent incomingEvent)
124             throws StateMachineException, ContextException {
125         // Check if there are any states on the state machine
126         if (stateExecutorMap.size() == 0) {
127             throw new StateMachineException("no states defined on state machine");
128         }
129
130         // Check if the first state of the machine is defined
131         if (firstExecutor == null) {
132             throw new StateMachineException("first state not defined on state machine");
133         }
134
135         // Get the first state of the state machine and define a state output that starts state
136         // execution
137         StateExecutor stateExecutor = firstExecutor;
138         StateOutput stateOutput = new StateOutput(new AxStateOutput(firstExecutor.getSubject().getKey(),
139                 incomingEvent.getKey(), firstExecutor.getSubject().getKey()), incomingEvent);
140
141         while (true) {
142             // Execute the state, it returns an output or throws an exception
143             stateOutput = stateExecutor.execute(executionId, executionProperties, stateOutput.getOutputEvent());
144
145             // Use the next state of the state output to find if all the states have executed
146             if (stateOutput.getNextState().equals(AxReferenceKey.getNullKey())) {
147                 break;
148             }
149
150             // Use the next state of the state output to find the next state
151             stateExecutor = stateExecutorMap.get(stateOutput.getNextState());
152             if (stateExecutor == null) {
153                 throw new StateMachineException(
154                         "state execution failed, next state \"" + stateOutput.getNextState().getId() + "\" not found");
155             }
156         }
157
158         return stateOutput.getOutputEvent();
159     }
160
161     /**
162      * {@inheritDoc}.
163      */
164     @Override
165     public final void executePre(final long executionId, final Properties executionProperties,
166             final EnEvent incomingEntity) throws StateMachineException {
167         throw new StateMachineException("execution pre work not implemented on class");
168     }
169
170     /**
171      * {@inheritDoc}.
172      */
173     @Override
174     public final void executePost(final boolean returnValue) throws StateMachineException {
175         throw new StateMachineException("execution post work not implemented on class");
176     }
177
178     /**
179      * {@inheritDoc}.
180      */
181     @Override
182     public void cleanUp() throws StateMachineException {
183         for (final StateExecutor stateExecutor : stateExecutorMap.values()) {
184             stateExecutor.cleanUp();
185         }
186     }
187
188     /**
189      * {@inheritDoc}.
190      */
191     @Override
192     public AxArtifactKey getKey() {
193         return axPolicy.getKey();
194     }
195
196     /**
197      * {@inheritDoc}.
198      */
199     @Override
200     public final Executor<?, ?, ?, ?> getParent() {
201         return parent;
202     }
203
204     /**
205      * {@inheritDoc}.
206      */
207     @Override
208     public final AxPolicy getSubject() {
209         return axPolicy;
210     }
211
212     /**
213      * {@inheritDoc}.
214      */
215     @Override
216     public final ApexInternalContext getContext() {
217         return internalContext;
218     }
219
220     /**
221      * {@inheritDoc}.
222      */
223     @Override
224     public final EnEvent getIncoming() {
225         return null;
226     }
227
228     /**
229      * {@inheritDoc}.
230      */
231     @Override
232     public final EnEvent getOutgoing() {
233         return null;
234     }
235
236     /**
237      * {@inheritDoc}.
238      */
239     @Override
240     public final void setNext(final Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> newNextExecutor) {
241         this.nextExecutor = newNextExecutor;
242     }
243
244     /**
245      * {@inheritDoc}.
246      */
247     @Override
248     public final Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> getNext() {
249         return nextExecutor;
250     }
251
252     /**
253      * {@inheritDoc}.
254      */
255     @Override
256     public void setParameters(final ExecutorParameters parameters) {
257         // Not implemented in this class
258     }
259 }