2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2021 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.eventmanager;
 
  23 import java.util.Deque;
 
  24 import java.util.LinkedList;
 
  25 import java.util.UUID;
 
  26 import java.util.stream.Collectors;
 
  28 import lombok.ToString;
 
  29 import org.drools.core.WorkingMemory;
 
  30 import org.onap.policy.controlloop.ControlLoopException;
 
  31 import org.onap.policy.controlloop.ControlLoopNotificationType;
 
  32 import org.onap.policy.controlloop.ControlLoopOperation;
 
  33 import org.onap.policy.controlloop.ControlLoopResponse;
 
  34 import org.onap.policy.controlloop.VirtualControlLoopNotification;
 
  35 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 
  36 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
 
  37 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
 
  38 import org.onap.policy.drools.domain.models.operational.OperationalTarget;
 
  41  * Manager for a single control loop event, with operation outcomes.
 
  43 public abstract class ClEventManagerWithOutcome<T extends Step> extends ClEventManagerWithSteps<T>
 
  44                 implements StepContext {
 
  46     private static final long serialVersionUID = -1216568161322872641L;
 
  49      * Number of attempts, so far, for the current step.
 
  55      * Full history of operations that have been processed by the rules. This includes the
 
  56      * items in {@link #partialHistory}.
 
  59     private final transient Deque<OperationOutcome2> fullHistory = new LinkedList<>();
 
  62      * History of operations that have been processed by the rules for the current policy.
 
  63      * When a step is started, its "start" outcome is added. However, once it completes,
 
  64      * its "start" outcome is removed and the "completed" outcome is added.
 
  67     private final transient Deque<OperationOutcome2> partialHistory = new LinkedList<>();
 
  71      * Constructs the object.
 
  73      * @param services services the manager should use when processing the event
 
  74      * @param params control loop parameters
 
  75      * @param requestId event request ID
 
  76      * @param workMem working memory to update if this changes
 
  77      * @throws ControlLoopException if the event is invalid or if a YAML processor cannot
 
  80     protected ClEventManagerWithOutcome(EventManagerServices services, ControlLoopParams params, UUID requestId,
 
  81                     WorkingMemory workMem) throws ControlLoopException {
 
  83         super(services, params, requestId, workMem);
 
  87     protected void loadPolicy() throws ControlLoopException {
 
  88         partialHistory.clear();
 
  93     public boolean executeStep() {
 
  95         return super.executeStep();
 
  99      * Increments the number of attempts.
 
 101     public void bumpAttempts() {
 
 106      * Determines if the TOSCA should be aborted due to the given outcome.
 
 108      * @param outcome outcome to examine
 
 109      * @return {@code true} if the TOSCA should be aborted, {@code false} otherwise
 
 111     public boolean isAbort(OperationOutcome outcome) {
 
 112         return (outcome.getResult() != OperationResult.SUCCESS);
 
 116      * Adds the outcome to the history.
 
 118      * @param outcome outcome to add
 
 120     public void addToHistory(OperationOutcome outcome) {
 
 121         OperationOutcome2 last = partialHistory.peekLast();
 
 123         if (last != null && last.getOutcome().getEnd() == null
 
 124                         && last.getOutcome().isFor(outcome.getActor(), outcome.getOperation())) {
 
 125             // last item was a "start" - remove it
 
 126             partialHistory.removeLast();
 
 128             if (fullHistory.peekLast() == last) {
 
 129                 fullHistory.removeLast();
 
 133         var outcome2 = makeOperationOutcome2(outcome);
 
 134         partialHistory.add(outcome2);
 
 135         fullHistory.add(outcome2);
 
 139      * Makes a notification message for the current operation.
 
 141      * @return a new notification
 
 143     public VirtualControlLoopNotification makeNotification() {
 
 144         var notif = new VirtualControlLoopNotification();
 
 145         populateNotification(notif);
 
 147         if (getFinalResult() != null) {
 
 151         OperationOutcome2 last = partialHistory.peekLast();
 
 156         notif.setMessage(last.getClOperation().toHistory());
 
 157         notif.setHistory(partialHistory.stream().map(OperationOutcome2::getClOperation).collect(Collectors.toList()));
 
 163      * Populates a notification structure.
 
 165      * @param notif the notification to populate
 
 167     protected void populateNotification(VirtualControlLoopNotification notif) {
 
 168         notif.setNotification(ControlLoopNotificationType.OPERATION);
 
 169         notif.setFrom("policy");
 
 170         notif.setPolicyVersion(getPolicyVersion());
 
 174      * Get the last operation, as a message.
 
 176      * @return the last operation, as a message
 
 178     public String getOperationMessage() {
 
 179         OperationOutcome2 last = fullHistory.peekLast();
 
 180         return (last == null ? null : last.getClOperation().toMessage());
 
 184      * Makes a control loop response.
 
 186      * @param outcome operation outcome
 
 187      * @return a new control loop response, or {@code null} if none is required
 
 189     public ControlLoopResponse makeControlLoopResponse(OperationOutcome outcome) {
 
 190         var clRsp = new ControlLoopResponse();
 
 191         clRsp.setFrom(outcome.getActor());
 
 198     public class OperationOutcome2 {
 
 199         private final int attempt;
 
 200         private final OperationOutcome outcome;
 
 201         private final ControlLoopOperation clOperation;
 
 204          * Constructs the object.
 
 206          * @param outcome outcome of the operation
 
 208         public OperationOutcome2(OperationOutcome outcome) {
 
 209             this.outcome = outcome;
 
 210             this.attempt = attempts;
 
 212             clOperation = outcome.toControlLoopOperation();
 
 215             OperationalTarget target = getPolicy().getActorOperation().getTarget();
 
 216             String targetStr = (target != null ? target.toString() : null);
 
 217             clOperation.setTarget(targetStr);
 
 219             if (outcome.getEnd() == null) {
 
 220                 clOperation.setOutcome("Started");
 
 221             } else if (clOperation.getOutcome() == null) {
 
 222                 clOperation.setOutcome("");
 
 227     protected OperationOutcome2 makeOperationOutcome2(OperationOutcome outcome) {
 
 228         return new OperationOutcome2(outcome);