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