/*-
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
* Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
*/
package org.onap.policy.controlloop.actorserviceprovider.parameters;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Consumer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.common.parameters.BeanValidator;
import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.controlloop.ControlLoopOperation;
import org.onap.policy.controlloop.actorserviceprovider.ActorService;
import org.onap.policy.controlloop.actorserviceprovider.Util;
import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
import org.onap.policy.controlloop.policy.Policy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Parameters for control loop operations. The executor defaults to
* {@link ForkJoinPool#commonPool()}, but may be overridden.
*/
@Getter
@Builder(toBuilder = true)
@AllArgsConstructor
@EqualsAndHashCode
public class ControlLoopOperationParams {
private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationParams.class);
public static final String UNKNOWN = "-unknown-";
/**
* The actor service in which to find the actor/operation.
*/
@NotNull
private ActorService actorService;
/**
* The event for which the operation applies.
*/
@NotNull
private ControlLoopEventContext context;
/**
* The executor to use to run the operation.
*/
@NotNull
@Builder.Default
private Executor executor = ForkJoinPool.commonPool();
/**
* The policy associated with the operation.
*/
@NotNull
private Policy policy;
/**
* The function to invoke when the operation starts. This is optional.
*
* Note: this may be invoked multiple times, but with different actor/operations. That
* may happen if the current operation requires other operations to be performed first
* (e.g., A&AI queries, guard checks).
*/
private Consumer startCallback;
/**
* The function to invoke when the operation completes. This is optional.
*
* Note: this may be invoked multiple times, but with different actor/operations. That
* may happen if the current operation requires other operations to be performed first
* (e.g., A&AI queries, guard checks).
*/
private Consumer completeCallback;
/**
* Target entity.
*/
@NotNull
private String target;
/**
* Starts the specified operation.
*
* @return a future that will return the result of the operation
* @throws IllegalArgumentException if the parameters are invalid
*/
public CompletableFuture start() {
BeanValidationResult result = validate();
if (!result.isValid()) {
logger.warn("parameter error in operation {}.{} for {}:\n{}", getActor(), getOperation(), getRequestId(),
result.getResult());
throw new IllegalArgumentException("invalid parameters");
}
// @formatter:off
return actorService
.getActor(policy.getActor())
.getOperator(policy.getRecipe())
.startOperation(this);
// @formatter:on
}
/**
* Gets the name of the actor from the policy.
*
* @return the actor name, or {@link #UNKNOWN} if no name is available
*/
public String getActor() {
return (policy == null || policy.getActor() == null ? UNKNOWN : policy.getActor());
}
/**
* Gets the name of the operation from the policy.
*
* @return the operation name, or {@link #UNKNOWN} if no name is available
*/
public String getOperation() {
return (policy == null || policy.getRecipe() == null ? UNKNOWN : policy.getRecipe());
}
/**
* Gets the requested ID of the associated event.
*
* @return the event's request ID, or {@code null} if no request ID is available
*/
public UUID getRequestId() {
return (context == null || context.getEvent() == null ? null : context.getEvent().getRequestId());
}
/**
* Makes an operation outcome, populating it from the parameters.
*
* @return a new operation outcome
*/
public ControlLoopOperation makeOutcome() {
ControlLoopOperation operation = new ControlLoopOperation();
operation.setActor(getActor());
operation.setOperation(getOperation());
operation.setTarget(target);
return operation;
}
/**
* Invokes the callback to indicate that the operation has started. Any exceptions
* generated by the callback are logged, but not re-thrown.
*
* @param operation the operation that is being started
*/
public void callbackStarted(ControlLoopOperation operation) {
logger.info("started operation {}.{} for {}", operation.getActor(), operation.getOperation(), getRequestId());
if (startCallback != null) {
Util.logException(() -> startCallback.accept(operation), "{}.{}: start-callback threw an exception for {}",
operation.getActor(), operation.getOperation(), getRequestId());
}
}
/**
* Invokes the callback to indicate that the operation has completed. Any exceptions
* generated by the callback are logged, but not re-thrown.
*
* @param operation the operation that is being started
*/
public void callbackCompleted(ControlLoopOperation operation) {
logger.info("completed operation {}.{} outcome={} for {}", operation.getActor(), operation.getOperation(),
operation.getOutcome(), getRequestId());
if (completeCallback != null) {
Util.logException(() -> completeCallback.accept(operation),
"{}.{}: complete-callback threw an exception for {}", operation.getActor(),
operation.getOperation(), getRequestId());
}
}
/**
* Validates the parameters.
*
* @return the validation result
*/
public BeanValidationResult validate() {
return new BeanValidator().validateTop(ControlLoopOperationParams.class.getSimpleName(), this);
}
}