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.parameters;
24 import java.util.UUID;
25 import java.util.concurrent.CompletableFuture;
26 import java.util.concurrent.Executor;
27 import java.util.concurrent.ForkJoinPool;
28 import java.util.function.Consumer;
29 import lombok.AllArgsConstructor;
30 import lombok.Builder;
31 import lombok.EqualsAndHashCode;
33 import org.onap.policy.common.parameters.BeanValidationResult;
34 import org.onap.policy.common.parameters.BeanValidator;
35 import org.onap.policy.common.parameters.annotations.NotNull;
36 import org.onap.policy.controlloop.VirtualControlLoopEvent;
37 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
38 import org.onap.policy.controlloop.actorserviceprovider.Operation;
39 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
40 import org.onap.policy.controlloop.actorserviceprovider.Util;
41 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
42 import org.onap.policy.controlloop.policy.Target;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 * Parameters for control loop operations. The executor defaults to
48 * {@link ForkJoinPool#commonPool()}, but may be overridden.
51 @Builder(toBuilder = true)
54 public class ControlLoopOperationParams {
55 private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationParams.class);
64 * Actor service in which to find the actor/operation.
67 private ActorService actorService;
70 * Event for which the operation applies.
73 private ControlLoopEventContext context;
76 * If {@code null}, this value is extracted from the context.
78 private UUID requestId;
81 * Executor to use to run the operation.
85 private Executor executor = ForkJoinPool.commonPool();
91 private String operation;
94 * Payload data for the request.
96 private Map<String, Object> payload;
99 * {@code True} if the preprocessing steps have already been executed, {@code false}
102 private boolean preprocessed;
105 * Number of retries allowed, or {@code null} if no retries.
107 private Integer retry;
110 * The Target information, extracted from the Policy. May be {@code null}, depending
111 * on the requirement of the operation to be invoked.
113 private Target target;
118 // TODO to be removed
119 private String targetEntity;
122 * Timeout, in seconds, or {@code null} if no timeout. Zero and negative values also
126 private Integer timeoutSec = 300;
129 * The function to invoke when the operation starts. This is optional.
131 * Note: this may be invoked multiple times, but with different actor/operations. That
132 * may happen if the current operation requires other operations to be performed first
133 * (e.g., A&AI queries, guard checks).
135 private Consumer<OperationOutcome> startCallback;
138 * The function to invoke when the operation completes. This is optional.
140 * Note: this may be invoked multiple times, but with different actor/operations. That
141 * may happen if the current operation requires other operations to be performed first
142 * (e.g., A&AI queries, guard checks).
144 private Consumer<OperationOutcome> completeCallback;
147 * Starts the specified operation.
149 * @return a future that will return the result of the operation
150 * @throws IllegalArgumentException if the parameters are invalid
152 public CompletableFuture<OperationOutcome> start() {
153 return build().start();
157 * Builds the specified operation.
159 * @return a new operation
160 * @throws IllegalArgumentException if the parameters are invalid
162 public Operation build() {
163 BeanValidationResult result = validate();
164 if (!result.isValid()) {
165 logger.warn("parameter error in operation {}.{} for {}:\n{}", getActor(), getOperation(), getRequestId(),
167 throw new IllegalArgumentException("invalid parameters");
172 .getActor(getActor())
173 .getOperator(getOperation())
174 .buildOperation(this);
179 * Gets the requested ID of the associated event.
181 * @return the event's request ID, or {@code null} if no request ID is available
183 public UUID getRequestId() {
184 if (requestId == null && context != null && context.getEvent() != null) {
185 // cache the request ID
186 requestId = context.getEvent().getRequestId();
193 * Makes an operation outcome, populating it from the parameters.
195 * @return a new operation outcome
197 // TODO to be removed
198 public OperationOutcome makeOutcome() {
199 return makeOutcome(getTargetEntity());
203 * Makes an operation outcome, populating it from the parameters.
205 * @param targetEntity the target entity
207 * @return a new operation outcome
209 public OperationOutcome makeOutcome(String targetEntity) {
210 OperationOutcome outcome = new OperationOutcome();
211 outcome.setActor(getActor());
212 outcome.setOperation(getOperation());
213 outcome.setTarget(targetEntity);
219 * Invokes the callback to indicate that the operation has started. Any exceptions
220 * generated by the callback are logged, but not re-thrown.
222 * @param operation the operation that is being started
224 public void callbackStarted(OperationOutcome operation) {
225 logger.info("started operation {}.{} for {}", operation.getActor(), operation.getOperation(), getRequestId());
227 if (startCallback != null) {
228 Util.runFunction(() -> startCallback.accept(operation), "{}.{}: start-callback threw an exception for {}",
229 operation.getActor(), operation.getOperation(), getRequestId());
234 * Invokes the callback to indicate that the operation has completed. Any exceptions
235 * generated by the callback are logged, but not re-thrown.
237 * @param operation the operation that is being started
239 public void callbackCompleted(OperationOutcome operation) {
240 logger.info("completed operation {}.{} outcome={} for {}", operation.getActor(), operation.getOperation(),
241 operation.getResult(), getRequestId());
243 if (completeCallback != null) {
244 Util.runFunction(() -> completeCallback.accept(operation),
245 "{}.{}: complete-callback threw an exception for {}", operation.getActor(),
246 operation.getOperation(), getRequestId());
251 * Validates the parameters.
253 * @return the validation result
255 public BeanValidationResult validate() {
256 BeanValidationResult result =
257 new BeanValidator().validateTop(ControlLoopOperationParams.class.getSimpleName(), this);
259 // validate that we have a request ID, or that we can get it from the context's
262 if (context == null) {
263 // no context specified - invoker must provide a request ID then
264 result.validateNotNull("requestId", requestId);
266 } else if (requestId == null) {
267 // have a context, but no request ID - check the context's event for the
269 BeanValidationResult contextResult = new BeanValidationResult("context", context);
270 VirtualControlLoopEvent event = context.getEvent();
271 contextResult.validateNotNull("event", event);
274 // cache the request id for later use
275 BeanValidationResult eventResult = new BeanValidationResult("event", event);
276 eventResult.validateNotNull("requestId", event.getRequestId());
278 contextResult.addResult(eventResult);
281 result.addResult(contextResult);