f490a984917e8b2ee937eb0bd16d87eda06220f4
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
5  *  Modifications Copyright (C) 2021 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.apex.core.engine.executor;
24
25 import static org.onap.policy.common.utils.validation.Assertions.argumentOfClassNotNull;
26
27 import java.util.Map;
28 import java.util.Properties;
29 import lombok.AccessLevel;
30 import lombok.Getter;
31 import lombok.NonNull;
32 import org.onap.policy.apex.context.ContextException;
33 import org.onap.policy.apex.core.engine.ExecutorParameters;
34 import org.onap.policy.apex.core.engine.context.ApexInternalContext;
35 import org.onap.policy.apex.core.engine.executor.context.StateFinalizerExecutionContext;
36 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
37 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
38 import org.onap.policy.apex.model.policymodel.concepts.AxState;
39 import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
40 import org.slf4j.ext.XLogger;
41 import org.slf4j.ext.XLoggerFactory;
42
43 /**
44  * This abstract class executes state finalizer logic in a state of an Apex policy and is specialized by classes that
45  * implement execution of state finalizer logic.
46  *
47  * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
48  * @author Liam Fallon (liam.fallon@ericsson.com)
49  */
50 public abstract class StateFinalizerExecutor
51         implements Executor<Map<String, Object>, String, AxStateFinalizerLogic, ApexInternalContext> {
52     // Logger for this class
53     private static final XLogger LOGGER = XLoggerFactory.getXLogger(StateFinalizerExecutor.class);
54
55     // Repeated string constants
56     private static final String EXECUTE_POST_SFL = "execute-post: state finalizer logic \"";
57
58     // Hold the state and context definitions
59     @Getter
60     private Executor<?, ?, ?, ?> parent = null;
61     private AxState axState = null;
62     private AxStateFinalizerLogic finalizerLogic = null;
63     private ApexInternalContext internalContext = null;
64
65     // Holds the incoming and outgoing fields
66     private Map<String, Object> incomingFields = null;
67
68     // The next state finalizer executor
69     private Executor<Map<String, Object>, String, AxStateFinalizerLogic, ApexInternalContext> nextExecutor = null;
70
71     // The execution context; contains the facades for events and context to be used by tasks
72     // executed by this task
73     // executor
74     @Getter(AccessLevel.PROTECTED)
75     private StateFinalizerExecutionContext executionContext = null;
76
77     /**
78      * {@inheritDoc}.
79      */
80     @Override
81     public void setContext(final Executor<?, ?, ?, ?> incomingParent,
82             final AxStateFinalizerLogic incomingFinalizerLogic, final ApexInternalContext incomingInternalContext) {
83         this.parent = incomingParent;
84         axState = (AxState) parent.getSubject();
85         this.finalizerLogic = incomingFinalizerLogic;
86         this.internalContext = incomingInternalContext;
87     }
88
89     /**
90      * {@inheritDoc}.
91      */
92     @Override
93     public void prepare() throws StateMachineException {
94         LOGGER.debug("prepare:" + finalizerLogic.getId() + "," + finalizerLogic.getLogicFlavour() + ","
95                 + finalizerLogic.getLogic());
96         argumentOfClassNotNull(finalizerLogic.getLogic(), StateMachineException.class,
97                 "state finalizer logic cannot be null.");
98     }
99
100     /**
101      * {@inheritDoc}.
102      */
103     @Override
104     public String execute(final long executionId, final Properties executionProperties,
105             final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException {
106         throw new StateMachineException("execute() not implemented on abstract StateFinalizerExecutionContext class, "
107                 + "only on its subclasses");
108     }
109
110     /**
111      * {@inheritDoc}.
112      */
113     @Override
114     public final void executePre(final long executionId, @NonNull final Properties executionProperties,
115             final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException {
116         LOGGER.debug("execute-pre:" + finalizerLogic.getLogicFlavour() + "," + getSubject().getId() + ","
117                 + finalizerLogic.getLogic());
118
119         // Record the incoming fields
120         this.incomingFields = newIncomingFields;
121
122         // Get state finalizer context object
123         executionContext = new StateFinalizerExecutionContext(this, executionId, executionProperties, axState,
124                 getIncoming(), axState.getStateOutputs().keySet(), getContext());
125     }
126
127     /**
128      * {@inheritDoc}.
129      */
130     @Override
131     public final void executePost(final boolean returnValue) throws StateMachineException, ContextException {
132         if (!returnValue) {
133             String errorMessage = "execute-post: state finalizer logic execution failure on state \"" + axState.getId()
134                     + "\" on finalizer logic " + finalizerLogic.getId();
135             if (executionContext.getMessage() != null) {
136                 errorMessage += ", user message: " + executionContext.getMessage();
137             }
138             LOGGER.warn(errorMessage);
139             throw new StateMachineException(errorMessage);
140         }
141
142         // Check a state output has been selected
143         if (getOutgoing() == null) {
144             String message = EXECUTE_POST_SFL + finalizerLogic.getId() + "\" did not select an output state";
145             LOGGER.warn(message);
146             throw new StateMachineException(message);
147         }
148
149         if (!axState.getStateOutputs().keySet().contains(getOutgoing())) {
150             LOGGER.warn(EXECUTE_POST_SFL + finalizerLogic.getId() + "\" selected output state \"" + getOutgoing()
151                     + "\" that does not exsist on state \"" + axState.getId() + "\"");
152             throw new StateMachineException(EXECUTE_POST_SFL + finalizerLogic.getId() + "\" selected output state \""
153                     + getOutgoing() + "\" that does not exsist on state \"" + axState.getId() + "\"");
154         }
155
156         LOGGER.debug("execute-post:{}, returning  state output \"{}\" and fields {}", finalizerLogic.getId(),
157                 getOutgoing(), incomingFields);
158     }
159
160     /**
161      * {@inheritDoc}.
162      */
163     @Override
164     public void cleanUp() throws StateMachineException {
165         throw new StateMachineException("cleanUp() not implemented on class");
166     }
167
168     /**
169      * {@inheritDoc}.
170      */
171     @Override
172     public AxReferenceKey getKey() {
173         return finalizerLogic.getKey();
174     }
175
176     /**
177      * {@inheritDoc}.
178      */
179     @Override
180     public AxStateFinalizerLogic getSubject() {
181         return finalizerLogic;
182     }
183
184     /**
185      * {@inheritDoc}.
186      */
187     @Override
188     public ApexInternalContext getContext() {
189         return internalContext;
190     }
191
192     /**
193      * {@inheritDoc}.
194      */
195     @Override
196     public Map<String, Object> getIncoming() {
197         return incomingFields;
198     }
199
200     /**
201      * {@inheritDoc}.
202      */
203     @Override
204     public String getOutgoing() {
205         if (executionContext != null) {
206             return executionContext.getSelectedStateOutputName();
207         } else {
208             return null;
209         }
210     }
211
212     /**
213      * {@inheritDoc}.
214      */
215     @Override
216     public void setNext(
217             final Executor<Map<String, Object>, String, AxStateFinalizerLogic, ApexInternalContext> inNextEx) {
218         this.nextExecutor = inNextEx;
219     }
220
221     /**
222      * {@inheritDoc}.
223      */
224     @Override
225     public Executor<Map<String, Object>, String, AxStateFinalizerLogic, ApexInternalContext> getNext() {
226         return nextExecutor;
227     }
228
229     /**
230      * {@inheritDoc}.
231      */
232     @Override
233     public void setParameters(final ExecutorParameters parameters) {
234         // Not used
235     }
236 }