2  * ============LICENSE_START=======================================================
 
   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
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  21 package org.onap.policy.controlloop.actorserviceprovider.impl;
 
  23 import java.util.Collection;
 
  24 import java.util.Collections;
 
  25 import java.util.List;
 
  28 import java.util.concurrent.ConcurrentHashMap;
 
  29 import java.util.function.Function;
 
  30 import org.onap.policy.common.parameters.BeanValidationResult;
 
  31 import org.onap.policy.controlloop.actorserviceprovider.Operator;
 
  32 import org.onap.policy.controlloop.actorserviceprovider.Util;
 
  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;
 
  39  * Implementation of an actor.
 
  41 public class ActorImpl extends StartConfigPartial<Map<String, Object>> implements Actor {
 
  42     private static final Logger logger = LoggerFactory.getLogger(ActorImpl.class);
 
  45      * Maps a name to an operator.
 
  47     private final Map<String, Operator> name2operator = new ConcurrentHashMap<>();
 
  50      * Constructs the object.
 
  52      * @param name actor name
 
  54     public ActorImpl(String name) {
 
  59      * Adds an operator supported by this actor.
 
  61      * @param operator operation to be added
 
  63     protected synchronized void addOperator(Operator operator) {
 
  65          * This method is "synchronized" to prevent the state from changing while the
 
  66          * operator is added. The map, itself, does not need synchronization as it's a
 
  71             throw new IllegalStateException("attempt to set operators on a configured actor: " + getName());
 
  74         name2operator.compute(operator.getName(), (opName, existingOp) -> {
 
  75             if (existingOp == null) {
 
  79             logger.warn("duplicate names for actor operation {}.{}: {}, ignoring {}", getName(), opName,
 
  80                             existingOp.getClass().getSimpleName(), operator.getClass().getSimpleName());
 
  86     public String getName() {
 
  91     public Operator getOperator(String name) {
 
  92         Operator operator = name2operator.get(name);
 
  93         if (operator == null) {
 
  94             throw new IllegalArgumentException("unknown operation " + getName() + "." + name);
 
 101     public Collection<Operator> getOperators() {
 
 102         return name2operator.values();
 
 106     public Set<String> getOperationNames() {
 
 107         return name2operator.keySet();
 
 111      * For each operation, it looks for a set of parameters by the same name and, if
 
 112      * found, configures the operation with the parameters.
 
 115     protected void doConfigure(Map<String, Object> parameters) {
 
 116         final String actorName = getName();
 
 117         logger.info("configuring operations for actor {}", actorName);
 
 119         BeanValidationResult valres = new BeanValidationResult(actorName, parameters);
 
 121         // function that creates operator-specific parameters, given the operation name
 
 122         Function<String, Map<String, Object>> opParamsMaker = makeOperatorParameters(parameters);
 
 124         for (Operator operator : name2operator.values()) {
 
 125             String operName = operator.getName();
 
 126             Map<String, Object> subparams = opParamsMaker.apply(operName);
 
 128             if (subparams != null) {
 
 131                     operator.configure(subparams);
 
 133                 } catch (ParameterValidationRuntimeException e) {
 
 134                     logger.warn("failed to configure operation {}.{}", actorName, operName, e);
 
 135                     valres.addResult(e.getResult());
 
 137                 } catch (RuntimeException e) {
 
 138                     logger.warn("failed to configure operation {}.{}", actorName, operName, e);
 
 141             } else if (operator.isConfigured()) {
 
 142                 logger.warn("missing configuration parameters for operation {}.{}; using previous parameters",
 
 143                                 actorName, operName);
 
 146                 logger.warn("missing configuration parameters for operation {}.{}; operation cannot be started",
 
 147                                 actorName, operName);
 
 153      * Extracts the operator parameters from the actor parameters, for a given operator.
 
 154      * This method assumes each operation has its own set of parameters.
 
 156      * @param actorParameters actor parameters
 
 157      * @return a function to extract the operator parameters from the actor parameters.
 
 158      *         Note: this function may return {@code null} if there are no parameters for
 
 159      *         the given operation name
 
 161     protected Function<String, Map<String, Object>> makeOperatorParameters(Map<String, Object> actorParameters) {
 
 163         return operName -> Util.translateToMap(getName() + "." + operName, actorParameters.get(operName));
 
 167      * Starts each operation.
 
 170     protected void doStart() {
 
 171         final String actorName = getName();
 
 172         logger.info("starting operations for actor {}", actorName);
 
 174         for (Operator oper : name2operator.values()) {
 
 175             if (oper.isConfigured()) {
 
 176                 Util.runFunction(oper::start, "failed to start operation {}.{}", actorName, oper.getName());
 
 179                 logger.warn("not starting unconfigured operation {}.{}", actorName, oper.getName());
 
 185      * Stops each operation.
 
 188     protected void doStop() {
 
 189         final String actorName = getName();
 
 190         logger.info("stopping operations for actor {}", actorName);
 
 193         name2operator.values().forEach(
 
 194             oper -> Util.runFunction(oper::stop, "failed to stop operation {}.{}", actorName, oper.getName()));
 
 199      * Shuts down each operation.
 
 202     protected void doShutdown() {
 
 203         final String actorName = getName();
 
 204         logger.info("shutting down operations for actor {}", actorName);
 
 207         name2operator.values().forEach(oper -> Util.runFunction(oper::shutdown,
 
 208                         "failed to shutdown operation {}.{}", actorName, oper.getName()));
 
 212     // TODO old code: remove lines down to **HERE**
 
 215     public String actor() {
 
 220     public List<String> recipes() {
 
 221         return Collections.emptyList();
 
 225     public List<String> recipeTargets(String recipe) {
 
 226         return Collections.emptyList();
 
 230     public List<String> recipePayloads(String recipe) {
 
 231         return Collections.emptyList();