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