58ee4c6ccb03588016489c46f051d592c33aeb2a
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.core.engine.executor.impl;
22
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.TreeMap;
26
27 import org.onap.policy.apex.core.engine.EngineParameters;
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.executor.Executor;
31 import org.onap.policy.apex.core.engine.executor.ExecutorFactory;
32 import org.onap.policy.apex.core.engine.executor.StateFinalizerExecutor;
33 import org.onap.policy.apex.core.engine.executor.TaskExecutor;
34 import org.onap.policy.apex.core.engine.executor.TaskSelectExecutor;
35 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
36 import org.onap.policy.apex.core.engine.executor.exception.StateMachineRuntimeException;
37 import org.onap.policy.apex.model.basicmodel.service.ParameterService;
38 import org.onap.policy.apex.model.policymodel.concepts.AxState;
39 import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
40 import org.onap.policy.apex.model.policymodel.concepts.AxTask;
41 import org.onap.policy.apex.model.utilities.Assertions;
42 import org.slf4j.ext.XLogger;
43 import org.slf4j.ext.XLoggerFactory;
44
45 /**
46  * The Class ExecutorFactoryImpl is a factory class that returns task selection logic and task logic executors depending
47  * on the type of logic executor has been specified for the task selection logic in a state or task logic in a task.
48  *
49  * @author Liam Fallon (liam.fallon@ericsson.com)
50  */
51 public class ExecutorFactoryImpl extends ExecutorFactory {
52     // Get a reference to the logger
53     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ExecutorFactoryImpl.class);
54
55     // A map of logic flavours mapped to executor classes for plugins to executors for those logic flavours
56     private Map<String, Class<Executor<?, ?, ?, ?>>> taskExecutorPluginClassMap =
57             new TreeMap<String, Class<Executor<?, ?, ?, ?>>>();
58     private Map<String, Class<Executor<?, ?, ?, ?>>> taskSelectionExecutorPluginClassMap =
59             new TreeMap<String, Class<Executor<?, ?, ?, ?>>>();
60     private Map<String, Class<Executor<?, ?, ?, ?>>> stateFinalizerExecutorPluginClassMap =
61             new TreeMap<String, Class<Executor<?, ?, ?, ?>>>();
62
63     // A map of parameters for executors
64     private final Map<String, ExecutorParameters> implementationParameterMap =
65             new TreeMap<String, ExecutorParameters>();
66
67     /**
68      * Constructor, builds the class map for executors.
69      *
70      * @throws StateMachineException on plugin creation errors
71      */
72     public ExecutorFactoryImpl() throws StateMachineException {
73         final EngineParameters engineParameters = ParameterService.getParameters(EngineParameters.class);
74
75         Assertions.argumentNotNull(engineParameters, StateMachineException.class,
76                 "Parameter \"engineParameters\" may not be null");
77
78         // Instantiate each executor class map entry
79         for (final Entry<String, ExecutorParameters> executorParameterEntry : engineParameters.getExecutorParameterMap()
80                 .entrySet()) {
81             // Get classes for all types of executors for this logic type
82             taskExecutorPluginClassMap.put(executorParameterEntry.getKey(),
83                     getExecutorPluginClass(executorParameterEntry.getValue().getTaskExecutorPluginClass()));
84             taskSelectionExecutorPluginClassMap.put(executorParameterEntry.getKey(),
85                     getExecutorPluginClass(executorParameterEntry.getValue().getTaskSelectionExecutorPluginClass()));
86             stateFinalizerExecutorPluginClassMap.put(executorParameterEntry.getKey(),
87                     getExecutorPluginClass(executorParameterEntry.getValue().getStateFinalizerExecutorPluginClass()));
88
89             // Save the executor implementation parameters
90             implementationParameterMap.put(executorParameterEntry.getKey(), executorParameterEntry.getValue());
91         }
92     }
93
94     /*
95      * (non-Javadoc)
96      *
97      * @see
98      * org.onap.policy.apex.core.engine.executor.ExecutorFactory#getTaskSelectionExecutor(org.onap.policy.apex.core.
99      * model. concepts.AxState, org.onap.policy.apex.core.engine.context.Context)
100      */
101     @Override
102     public TaskSelectExecutor getTaskSelectionExecutor(final Executor<?, ?, ?, ?> parentExecutor, final AxState state,
103             final ApexInternalContext context) {
104         if (!state.checkSetTaskSelectionLogic()) {
105             return null;
106         }
107
108         // Create task selection executor
109         final TaskSelectExecutor tsExecutor =
110                 (TaskSelectExecutor) createExecutor(state.getTaskSelectionLogic().getLogicFlavour(),
111                         taskSelectionExecutorPluginClassMap.get(state.getTaskSelectionLogic().getLogicFlavour()),
112                         TaskSelectExecutor.class);
113         tsExecutor.setParameters(implementationParameterMap.get(state.getTaskSelectionLogic().getLogicFlavour()));
114         tsExecutor.setContext(parentExecutor, state, context);
115
116         return tsExecutor;
117     }
118
119     /*
120      * (non-Javadoc)
121      *
122      * @see org.onap.policy.apex.core.engine.executor.ExecutorFactory#getTaskExecutor(org.onap.policy.apex.core.model.
123      * concepts. AxTask, org.onap.policy.apex.core.engine.context.Context)
124      */
125     @Override
126     public TaskExecutor getTaskExecutor(final Executor<?, ?, ?, ?> parentExecutor, final AxTask task,
127             final ApexInternalContext context) {
128         // Create task executor
129         final TaskExecutor taskExecutor = (TaskExecutor) createExecutor(task.getTaskLogic().getLogicFlavour(),
130                 taskExecutorPluginClassMap.get(task.getTaskLogic().getLogicFlavour()), TaskExecutor.class);
131         taskExecutor.setParameters(implementationParameterMap.get(task.getTaskLogic().getLogicFlavour()));
132         taskExecutor.setContext(parentExecutor, task, context);
133
134         return taskExecutor;
135     }
136
137     /*
138      * (non-Javadoc)
139      *
140      * @see
141      * org.onap.policy.apex.core.engine.executor.ExecutorFactory#getStateFinalizerExecutor(org.onap.policy.apex.core.
142      * engine. executor.Executor, org.onap.policy.apex.core.policymodel.concepts.AxStateFinalizerLogic,
143      * org.onap.policy.apex.core.engine.context.ApexInternalContext)
144      */
145     @Override
146     public StateFinalizerExecutor getStateFinalizerExecutor(final Executor<?, ?, ?, ?> parentExecutor,
147             final AxStateFinalizerLogic logic, final ApexInternalContext context) {
148         // Create state finalizer executor
149         final StateFinalizerExecutor sfExecutor = (StateFinalizerExecutor) createExecutor(logic.getLogicFlavour(),
150                 stateFinalizerExecutorPluginClassMap.get(logic.getLogicFlavour()), StateFinalizerExecutor.class);
151         sfExecutor.setParameters(implementationParameterMap.get(logic.getLogicFlavour()));
152         sfExecutor.setContext(parentExecutor, logic, context);
153
154         return sfExecutor;
155     }
156
157     /**
158      * Get an executor class for a given executor plugin class name.
159      *
160      * @param executorClassName The name of the executor plugin class
161      * @return an executor class
162      * @throws StateMachineException on plugin instantiation errors
163      */
164     @SuppressWarnings("unchecked")
165     private Class<Executor<?, ?, ?, ?>> getExecutorPluginClass(final String executorClassName)
166             throws StateMachineException {
167         // It's OK for an executor class not to be defined as long as it's not called
168         if (executorClassName == null) {
169             return null;
170         }
171
172         // Get the class for the executor using reflection
173         Class<? extends Object> executorPluginClass = null;
174         try {
175             executorPluginClass = Class.forName(executorClassName);
176         } catch (final ClassNotFoundException e) {
177             LOGGER.error("Apex executor class not found for executor plugin \"" + executorClassName + "\"", e);
178             throw new StateMachineException(
179                     "Apex executor class not found for executor plugin \"" + executorClassName + "\"", e);
180         }
181
182         // Check the class is an executor
183         if (!Executor.class.isAssignableFrom(executorPluginClass)) {
184             LOGGER.error("Specified Apex executor plugin class \"" + executorClassName
185                     + "\" does not implment the Executor interface");
186             throw new StateMachineException("Specified Apex executor plugin class \"" + executorClassName
187                     + "\" does not implment the Executor interface");
188         }
189
190         return (Class<Executor<?, ?, ?, ?>>) executorPluginClass;
191     }
192
193     /**
194      * Get an instance of an executor plugin class of the specified type and super type.
195      *
196      * @param logicFlavour The logic flavour of the logic
197      * @param executorClass The sub-class of the executor type to be instantiated
198      * @param executorSuperClass The super type of the class of executor to be instantiated
199      * @return The instantiated class
200      */
201     private Executor<?, ?, ?, ?> createExecutor(final String logicFlavour,
202             final Class<Executor<?, ?, ?, ?>> executorClass,
203             final Class<? extends Executor<?, ?, ?, ?>> executorSuperClass) {
204         // It's OK for an executor class not to be defined but it's not all right to try and create 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 a Task Selection 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 }