7bc437907e2e0ca9f048cf41efc616c67179e6d1
[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  * ================================================================================
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.impl;
23
24 import java.util.Map;
25 import java.util.Map.Entry;
26 import java.util.TreeMap;
27
28 import org.onap.policy.apex.core.engine.EngineParameterConstants;
29 import org.onap.policy.apex.core.engine.EngineParameters;
30 import org.onap.policy.apex.core.engine.ExecutorParameters;
31 import org.onap.policy.apex.core.engine.context.ApexInternalContext;
32 import org.onap.policy.apex.core.engine.executor.Executor;
33 import org.onap.policy.apex.core.engine.executor.ExecutorFactory;
34 import org.onap.policy.apex.core.engine.executor.StateFinalizerExecutor;
35 import org.onap.policy.apex.core.engine.executor.TaskExecutor;
36 import org.onap.policy.apex.core.engine.executor.TaskSelectExecutor;
37 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
38 import org.onap.policy.apex.core.engine.executor.exception.StateMachineRuntimeException;
39 import org.onap.policy.apex.model.policymodel.concepts.AxState;
40 import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
41 import org.onap.policy.apex.model.policymodel.concepts.AxTask;
42 import org.onap.policy.common.parameters.ParameterService;
43 import org.onap.policy.common.utils.validation.Assertions;
44 import org.slf4j.ext.XLogger;
45 import org.slf4j.ext.XLoggerFactory;
46
47 /**
48  * The Class ExecutorFactoryImpl is a factory class that returns task selection logic and task logic executors depending
49  * on the type of logic executor has been specified for the task selection logic in a state or task logic in a task.
50  *
51  * @author Liam Fallon (liam.fallon@ericsson.com)
52  */
53 public class ExecutorFactoryImpl implements ExecutorFactory {
54     // Get a reference to the logger
55     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ExecutorFactoryImpl.class);
56
57     // A map of logic flavours mapped to executor classes for plugins to executors for those logic flavours
58     private Map<String, Class<Executor<?, ?, ?, ?>>> taskExecutorPluginClassMap = new TreeMap<>();
59     private Map<String, Class<Executor<?, ?, ?, ?>>> taskSelectionExecutorPluginClassMap = new TreeMap<>();
60     private Map<String, Class<Executor<?, ?, ?, ?>>> stateFinalizerExecutorPluginClassMap = new TreeMap<>();
61
62     // A map of parameters for executors
63     private final Map<String, ExecutorParameters> implementationParameterMap = new TreeMap<>();
64
65     /**
66      * Constructor, builds the class map for executors.
67      *
68      * @throws StateMachineException on plugin creation errors
69      */
70     public ExecutorFactoryImpl() throws StateMachineException {
71         final EngineParameters engineParameters = ParameterService.get(EngineParameterConstants.MAIN_GROUP_NAME);
72
73         Assertions.argumentOfClassNotNull(engineParameters, StateMachineException.class,
74                         "Parameter \"engineParameters\" may not be null");
75
76         // Instantiate each executor class map entry
77         for (final Entry<String, ExecutorParameters> executorParameterEntry : engineParameters.getExecutorParameterMap()
78                         .entrySet()) {
79             // Get classes for all types of executors for this logic type
80             taskExecutorPluginClassMap.put(executorParameterEntry.getKey(),
81                             getExecutorPluginClass(executorParameterEntry.getValue().getTaskExecutorPluginClass()));
82             taskSelectionExecutorPluginClassMap.put(executorParameterEntry.getKey(), getExecutorPluginClass(
83                             executorParameterEntry.getValue().getTaskSelectionExecutorPluginClass()));
84             stateFinalizerExecutorPluginClassMap.put(executorParameterEntry.getKey(), getExecutorPluginClass(
85                             executorParameterEntry.getValue().getStateFinalizerExecutorPluginClass()));
86
87             // Save the executor implementation parameters
88             implementationParameterMap.put(executorParameterEntry.getKey(), executorParameterEntry.getValue());
89         }
90     }
91
92     /*
93      * (non-Javadoc)
94      *
95      * @see
96      * org.onap.policy.apex.core.engine.executor.ExecutorFactory#getTaskSelectionExecutor(org.onap.policy.apex.core.
97      * model. concepts.AxState, org.onap.policy.apex.core.engine.context.Context)
98      */
99     @Override
100     public TaskSelectExecutor getTaskSelectionExecutor(final Executor<?, ?, ?, ?> parentExecutor, final AxState state,
101                     final ApexInternalContext context) {
102         if (!state.checkSetTaskSelectionLogic()) {
103             return null;
104         }
105
106         // Create task selection executor
107         final TaskSelectExecutor tsExecutor = (TaskSelectExecutor) createExecutor(
108                         state.getTaskSelectionLogic().getLogicFlavour(),
109                         taskSelectionExecutorPluginClassMap.get(state.getTaskSelectionLogic().getLogicFlavour()),
110                         TaskSelectExecutor.class);
111         tsExecutor.setParameters(implementationParameterMap.get(state.getTaskSelectionLogic().getLogicFlavour()));
112         tsExecutor.setContext(parentExecutor, state, context);
113
114         return tsExecutor;
115     }
116
117     /*
118      * (non-Javadoc)
119      *
120      * @see org.onap.policy.apex.core.engine.executor.ExecutorFactory#getTaskExecutor(org.onap.policy.apex.core.model.
121      * concepts. AxTask, org.onap.policy.apex.core.engine.context.Context)
122      */
123     @Override
124     public TaskExecutor getTaskExecutor(final Executor<?, ?, ?, ?> parentExecutor, final AxTask task,
125                     final ApexInternalContext context) {
126         // Create task executor
127         final TaskExecutor taskExecutor = (TaskExecutor) createExecutor(task.getTaskLogic().getLogicFlavour(),
128                         taskExecutorPluginClassMap.get(task.getTaskLogic().getLogicFlavour()), TaskExecutor.class);
129         taskExecutor.setParameters(implementationParameterMap.get(task.getTaskLogic().getLogicFlavour()));
130         taskExecutor.setContext(parentExecutor, task, context);
131
132         return taskExecutor;
133     }
134
135     /*
136      * (non-Javadoc)
137      *
138      * @see
139      * org.onap.policy.apex.core.engine.executor.ExecutorFactory#getStateFinalizerExecutor(org.onap.policy.apex.core.
140      * engine. executor.Executor, org.onap.policy.apex.core.policymodel.concepts.AxStateFinalizerLogic,
141      * org.onap.policy.apex.core.engine.context.ApexInternalContext)
142      */
143     @Override
144     public StateFinalizerExecutor getStateFinalizerExecutor(final Executor<?, ?, ?, ?> parentExecutor,
145                     final AxStateFinalizerLogic logic, final ApexInternalContext context) {
146         // Create state finalizer executor
147         final StateFinalizerExecutor sfExecutor = (StateFinalizerExecutor) createExecutor(logic.getLogicFlavour(),
148                         stateFinalizerExecutorPluginClassMap.get(logic.getLogicFlavour()),
149                         StateFinalizerExecutor.class);
150         sfExecutor.setParameters(implementationParameterMap.get(logic.getLogicFlavour()));
151         sfExecutor.setContext(parentExecutor, logic, context);
152
153         return sfExecutor;
154     }
155
156     /**
157      * Get an executor class for a given executor plugin class name.
158      *
159      * @param executorClassName The name of the executor plugin class
160      * @return an executor class
161      * @throws StateMachineException on plugin instantiation errors
162      */
163     @SuppressWarnings("unchecked")
164     private Class<Executor<?, ?, ?, ?>> getExecutorPluginClass(final String executorClassName)
165                     throws StateMachineException {
166         // It's OK for an executor class not to be defined as long as it's not called
167         if (executorClassName == null) {
168             return null;
169         }
170
171         // Get the class for the executor using reflection
172         Class<? extends Object> executorPluginClass = null;
173         try {
174             executorPluginClass = Class.forName(executorClassName);
175         } catch (final ClassNotFoundException e) {
176             LOGGER.error("Apex executor class not found for executor plugin \"" + executorClassName + "\"", e);
177             throw new StateMachineException(
178                             "Apex executor class not found for executor plugin \"" + executorClassName + "\"", e);
179         }
180
181         // Check the class is an executor
182         if (!Executor.class.isAssignableFrom(executorPluginClass)) {
183             LOGGER.error("Specified Apex executor plugin class \"{}\" does not implment the Executor interface",
184                             executorClassName);
185             throw new StateMachineException("Specified Apex executor plugin class \"" + executorClassName
186                             + "\" does not implment the Executor interface");
187         }
188
189         return (Class<Executor<?, ?, ?, ?>>) executorPluginClass;
190     }
191
192     /**
193      * Get an instance of an executor plugin class of the specified type and super type.
194      *
195      * @param logicFlavour The logic flavour of the logic
196      * @param executorClass The sub-class of the executor type to be instantiated
197      * @param executorSuperClass The super type of the class of executor to be instantiated
198      * @return The instantiated class
199      */
200     private Executor<?, ?, ?, ?> createExecutor(final String logicFlavour,
201                     final Class<Executor<?, ?, ?, ?>> executorClass,
202                     final Class<? extends Executor<?, ?, ?, ?>> executorSuperClass) {
203         // It's OK for an executor class not to be defined but it's not all right to try and create
204         // a non-defined
205         // executor class
206         if (executorClass == null) {
207             final String errorMessage = "Executor plugin class not defined for \"" + logicFlavour
208                             + "\" executor of type \"" + executorSuperClass.getCanonicalName() + "\"";
209             LOGGER.error(errorMessage);
210             throw new StateMachineRuntimeException(errorMessage);
211         }
212
213         // Create an executor for the specified logic flavour
214         Object executorObject = null;
215         try {
216             executorObject = executorClass.newInstance();
217         } catch (InstantiationException | IllegalAccessException e) {
218             final String errorMessage = "Instantiation error on \"" + logicFlavour + "\" executor of type \""
219                             + executorClass.getCanonicalName() + "\"";
220             LOGGER.error(errorMessage, e);
221             throw new StateMachineRuntimeException(errorMessage, e);
222         }
223
224         // Check the class is the correct type of executor
225         if (!(executorSuperClass.isAssignableFrom(executorObject.getClass()))) {
226             final String errorMessage = "Executor on \"" + logicFlavour + "\" of type \"" + executorClass
227                             + "\" is not an instance of \"" + executorSuperClass.getCanonicalName() + "\"";
228
229             LOGGER.error(errorMessage);
230             throw new StateMachineRuntimeException(errorMessage);
231         }
232
233         return (Executor<?, ?, ?, ?>) executorObject;
234     }
235 }