2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.controlloop.eventmanager;
24 import java.io.Serial;
25 import java.util.Deque;
26 import java.util.LinkedList;
27 import java.util.UUID;
28 import java.util.stream.Collectors;
30 import lombok.ToString;
31 import org.drools.core.WorkingMemory;
32 import org.onap.policy.controlloop.ControlLoopException;
33 import org.onap.policy.controlloop.ControlLoopNotificationType;
34 import org.onap.policy.controlloop.ControlLoopOperation;
35 import org.onap.policy.controlloop.ControlLoopResponse;
36 import org.onap.policy.controlloop.VirtualControlLoopNotification;
37 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
38 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
39 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
40 import org.onap.policy.drools.domain.models.operational.OperationalTarget;
43 * Manager for a single control loop event, with operation outcomes.
46 public abstract class ClEventManagerWithOutcome<T extends Step> extends ClEventManagerWithSteps<T>
47 implements StepContext {
50 private static final long serialVersionUID = -1216568161322872641L;
53 * Number of attempts, so far, for the current step.
58 * Full history of operations that have been processed by the rules. This includes the
59 * items in {@link #partialHistory}.
61 private final transient Deque<OperationOutcome2> fullHistory = new LinkedList<>();
64 * History of operations that have been processed by the rules for the current policy.
65 * When a step is started, its "start" outcome is added. However, once it completes,
66 * its "start" outcome is removed and the "completed" outcome is added.
68 private final transient Deque<OperationOutcome2> partialHistory = new LinkedList<>();
72 * Constructs the object.
74 * @param services services the manager should use when processing the event
75 * @param params control loop parameters
76 * @param requestId event request ID
77 * @param workMem working memory to update if this changes
78 * @throws ControlLoopException if the event is invalid or if a YAML processor cannot
81 protected ClEventManagerWithOutcome(EventManagerServices services, ControlLoopParams params, UUID requestId,
82 WorkingMemory workMem) throws ControlLoopException {
84 super(services, params, requestId, workMem);
88 protected void loadPolicy() throws ControlLoopException {
89 partialHistory.clear();
94 public boolean executeStep() {
96 return super.executeStep();
100 * Increments the number of attempts.
102 public void bumpAttempts() {
107 * Determines if the TOSCA should be aborted due to the given outcome.
109 * @param outcome outcome to examine
110 * @return {@code true} if the TOSCA should be aborted, {@code false} otherwise
112 public boolean isAbort(OperationOutcome outcome) {
113 return (outcome.getResult() != OperationResult.SUCCESS);
117 * Adds the outcome to the history.
119 * @param outcome outcome to add
121 public void addToHistory(OperationOutcome outcome) {
122 OperationOutcome2 last = partialHistory.peekLast();
124 if (last != null && last.getOutcome().getEnd() == null
125 && last.getOutcome().isFor(outcome.getActor(), outcome.getOperation())) {
126 // last item was a "start" - remove it
127 partialHistory.removeLast();
129 if (fullHistory.peekLast() == last) {
130 fullHistory.removeLast();
134 var outcome2 = makeOperationOutcome2(outcome);
135 partialHistory.add(outcome2);
136 fullHistory.add(outcome2);
140 * Makes a notification message for the current operation.
142 * @return a new notification
144 public VirtualControlLoopNotification makeNotification() {
145 var notif = new VirtualControlLoopNotification();
146 populateNotification(notif);
148 if (getFinalResult() != null) {
152 OperationOutcome2 last = partialHistory.peekLast();
157 notif.setMessage(last.getClOperation().toHistory());
158 notif.setHistory(partialHistory.stream().map(OperationOutcome2::getClOperation).collect(Collectors.toList()));
164 * Populates a notification structure.
166 * @param notif the notification to populate
168 protected void populateNotification(VirtualControlLoopNotification notif) {
169 notif.setNotification(ControlLoopNotificationType.OPERATION);
170 notif.setFrom("policy");
171 notif.setPolicyVersion(getPolicyVersion());
175 * Get the last operation, as a message.
177 * @return the last operation, as a message
179 public String getOperationMessage() {
180 OperationOutcome2 last = fullHistory.peekLast();
181 return (last == null ? null : last.getClOperation().toMessage());
185 * Makes a control loop response.
187 * @param outcome operation outcome
188 * @return a new control loop response, or {@code null} if none is required
190 public ControlLoopResponse makeControlLoopResponse(OperationOutcome outcome) {
191 var clRsp = new ControlLoopResponse();
192 clRsp.setFrom(outcome.getActor());
199 public class OperationOutcome2 {
200 private final int attempt;
201 private final OperationOutcome outcome;
202 private final ControlLoopOperation clOperation;
205 * Constructs the object.
207 * @param outcome outcome of the operation
209 public OperationOutcome2(OperationOutcome outcome) {
210 this.outcome = outcome;
211 this.attempt = attempts;
213 clOperation = outcome.toControlLoopOperation();
216 OperationalTarget target = getPolicy().getActorOperation().getTarget();
217 String targetStr = (target != null ? target.toString() : null);
218 clOperation.setTarget(targetStr);
220 if (outcome.getEnd() == null) {
221 clOperation.setOutcome("Started");
222 } else if (clOperation.getOutcome() == null) {
223 clOperation.setOutcome("");
228 protected OperationOutcome2 makeOperationOutcome2(OperationOutcome outcome) {
229 return new OperationOutcome2(outcome);