c3c815e80c731f5b85006e5e6d320b0241026206
[policy/models.git] / models-interactions / model-actors / actorServiceProvider / src / main / java / org / onap / policy / controlloop / actorserviceprovider / impl / ActorImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 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  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.actorserviceprovider.impl;
22
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.function.Function;
30 import org.onap.policy.controlloop.actorserviceprovider.Operator;
31 import org.onap.policy.controlloop.actorserviceprovider.Util;
32 import org.onap.policy.controlloop.actorserviceprovider.parameters.ActorParams;
33 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
34 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Implementation of an actor.
40  */
41 public class ActorImpl extends StartConfigPartial<Map<String, Object>> implements Actor {
42     private static final Logger logger = LoggerFactory.getLogger(ActorImpl.class);
43
44     /**
45      * Maps a name to an operator.
46      */
47     private final Map<String, Operator> name2operator = new ConcurrentHashMap<>();
48
49     /**
50      * Constructs the object.
51      *
52      * @param name actor name
53      */
54     public ActorImpl(String name) {
55         super(name);
56     }
57
58     /**
59      * This method simply returns {@code 0}.
60      */
61     @Override
62     public int getSequenceNumber() {
63         return 0;
64     }
65
66     /**
67      * Adds an operator supported by this actor.
68      *
69      * @param operator operation to be added
70      */
71     protected synchronized void addOperator(Operator operator) {
72         /*
73          * This method is "synchronized" to prevent the state from changing while the
74          * operator is added. The map, itself, does not need synchronization as it's a
75          * concurrent map.
76          */
77
78         if (isConfigured()) {
79             throw new IllegalStateException("attempt to set operators on a configured actor: " + getName());
80         }
81
82         name2operator.compute(operator.getName(), (opName, existingOp) -> {
83             if (existingOp == null) {
84                 return operator;
85             }
86
87             logger.warn("duplicate names for actor operation {}.{}: {}, ignoring {}", getName(), opName,
88                             existingOp.getClass().getSimpleName(), operator.getClass().getSimpleName());
89             return existingOp;
90         });
91     }
92
93     @Override
94     public String getName() {
95         return getFullName();
96     }
97
98     @Override
99     public Operator getOperator(String name) {
100         Operator operator = name2operator.get(name);
101         if (operator == null) {
102             throw new IllegalArgumentException("unknown operator " + getName() + "." + name);
103         }
104
105         return operator;
106     }
107
108     @Override
109     public Collection<Operator> getOperators() {
110         return name2operator.values();
111     }
112
113     @Override
114     public Set<String> getOperationNames() {
115         return name2operator.keySet();
116     }
117
118     /**
119      * For each operation, it looks for a set of parameters by the same name and, if
120      * found, configures the operation with the parameters.
121      */
122     @Override
123     protected void doConfigure(Map<String, Object> parameters) {
124         final String actorName = getName();
125         logger.info("configuring operations for actor {}", actorName);
126
127         // function that creates operator-specific parameters, given the operation name
128         Function<String, Map<String, Object>> opParamsMaker = makeOperatorParameters(parameters);
129
130         for (Operator operator : name2operator.values()) {
131             String operName = operator.getName();
132             Map<String, Object> subparams = opParamsMaker.apply(operName);
133
134             if (subparams != null) {
135
136                 try {
137                     operator.configure(subparams);
138
139                 } catch (ParameterValidationRuntimeException e) {
140                     logger.warn("failed to configure operation {}.{} because:\n{}", actorName, operName,
141                                     e.getResult().getResult(), e);
142
143                 } catch (RuntimeException e) {
144                     logger.warn("failed to configure operation {}.{}", actorName, operName, e);
145                 }
146
147             } else if (operator.isConfigured()) {
148                 logger.warn("missing configuration parameters for operation {}.{}; using previous parameters",
149                                 actorName, operName);
150
151             } else {
152                 logger.warn("missing configuration parameters for operation {}.{}; operation cannot be started",
153                                 actorName, operName);
154             }
155         }
156     }
157
158     /**
159      * Extracts the operator parameters from the actor parameters, for a given operator.
160      * This method translates the parameters to an {@link ActorParams} and then creates a function
161      * that will extract operator-specific parameters.
162      *
163      * @param actorParameters actor parameters
164      * @return a function to extract the operator parameters from the actor parameters.
165      *         Note: this function may return {@code null} if there are no parameters for
166      *         the given operation name
167      */
168     protected Function<String, Map<String, Object>> makeOperatorParameters(Map<String, Object> actorParameters) {
169         String actorName = getName();
170
171         // @formatter:off
172         return Util.translate(actorName, actorParameters, ActorParams.class)
173                         .doValidation(actorName)
174                         .makeOperationParameters(actorName);
175         // @formatter:on
176     }
177
178     /**
179      * Starts each operation.
180      */
181     @Override
182     protected void doStart() {
183         final String actorName = getName();
184         logger.info("starting operations for actor {}", actorName);
185
186         for (Operator oper : name2operator.values()) {
187             if (oper.isConfigured()) {
188                 Util.runFunction(oper::start, "failed to start operation {}.{}", actorName, oper.getName());
189
190             } else {
191                 logger.warn("not starting unconfigured operation {}.{}", actorName, oper.getName());
192             }
193         }
194     }
195
196     /**
197      * Stops each operation.
198      */
199     @Override
200     protected void doStop() {
201         final String actorName = getName();
202         logger.info("stopping operations for actor {}", actorName);
203
204         // @formatter:off
205         name2operator.values().forEach(
206             oper -> Util.runFunction(oper::stop, "failed to stop operation {}.{}", actorName, oper.getName()));
207         // @formatter:on
208     }
209
210     /**
211      * Shuts down each operation.
212      */
213     @Override
214     protected void doShutdown() {
215         final String actorName = getName();
216         logger.info("shutting down operations for actor {}", actorName);
217
218         // @formatter:off
219         name2operator.values().forEach(oper -> Util.runFunction(oper::shutdown,
220                         "failed to shutdown operation {}.{}", actorName, oper.getName()));
221         // @formatter:on
222     }
223
224     // TODO old code: remove lines down to **HERE**
225
226     @Override
227     public String actor() {
228         return null;
229     }
230
231     @Override
232     public List<String> recipes() {
233         return Collections.emptyList();
234     }
235
236     @Override
237     public List<String> recipeTargets(String recipe) {
238         return Collections.emptyList();
239     }
240
241     @Override
242     public List<String> recipePayloads(String recipe) {
243         return Collections.emptyList();
244     }
245
246     // **HERE**
247 }