Make drools-pdp work with drools and java versions compatible
[policy/drools-applications.git] / controlloop / common / eventmanager / src / main / java / org / onap / policy / controlloop / eventmanager / ClEventManagerWithOutcome.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2023-2024 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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21
22 package org.onap.policy.controlloop.eventmanager;
23
24 import java.util.Deque;
25 import java.util.LinkedList;
26 import java.util.UUID;
27 import java.util.stream.Collectors;
28 import lombok.Getter;
29 import lombok.ToString;
30 import org.drools.core.WorkingMemory;
31 import org.onap.policy.controlloop.ControlLoopException;
32 import org.onap.policy.controlloop.ControlLoopNotificationType;
33 import org.onap.policy.controlloop.ControlLoopOperation;
34 import org.onap.policy.controlloop.ControlLoopResponse;
35 import org.onap.policy.controlloop.VirtualControlLoopNotification;
36 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
37 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
38 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
39 import org.onap.policy.drools.domain.models.operational.OperationalTarget;
40
41 /**
42  * Manager for a single control loop event, with operation outcomes.
43  */
44 @Getter
45 public abstract class ClEventManagerWithOutcome<T extends Step> extends ClEventManagerWithSteps<T>
46                 implements StepContext {
47
48     private static final long serialVersionUID = -1216568161322872641L;
49
50     /**
51      * Number of attempts, so far, for the current step.
52      */
53     private int attempts;
54
55     /**
56      * Full history of operations that have been processed by the rules. This includes the
57      * items in {@link #partialHistory}.
58      */
59     private final transient Deque<OperationOutcome2> fullHistory = new LinkedList<>();
60
61     /**
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.
65      */
66     private final transient Deque<OperationOutcome2> partialHistory = new LinkedList<>();
67
68
69     /**
70      * Constructs the object.
71      *
72      * @param services services the manager should use when processing the event
73      * @param params control loop parameters
74      * @param requestId event request ID
75      * @param workMem working memory to update if this changes
76      * @throws ControlLoopException if the event is invalid or if a YAML processor cannot
77      *         be created
78      */
79     protected ClEventManagerWithOutcome(EventManagerServices services, ControlLoopParams params, UUID requestId,
80                     WorkingMemory workMem) throws ControlLoopException {
81
82         super(services, params, requestId, workMem);
83     }
84
85     @Override
86     protected void loadPolicy() throws ControlLoopException {
87         partialHistory.clear();
88         super.loadPolicy();
89     }
90
91     @Override
92     public boolean executeStep() {
93         attempts = 0;
94         return super.executeStep();
95     }
96
97     /**
98      * Increments the number of attempts.
99      */
100     public void bumpAttempts() {
101         ++attempts;
102     }
103
104     /**
105      * Determines if the TOSCA should be aborted due to the given outcome.
106      *
107      * @param outcome outcome to examine
108      * @return {@code true} if the TOSCA should be aborted, {@code false} otherwise
109      */
110     public boolean isAbort(OperationOutcome outcome) {
111         return (outcome.getResult() != OperationResult.SUCCESS);
112     }
113
114     /**
115      * Adds the outcome to the history.
116      *
117      * @param outcome outcome to add
118      */
119     public void addToHistory(OperationOutcome outcome) {
120         OperationOutcome2 last = partialHistory.peekLast();
121
122         if (last != null && last.getOutcome().getEnd() == null
123                         && last.getOutcome().isFor(outcome.getActor(), outcome.getOperation())) {
124             // last item was a "start" - remove it
125             partialHistory.removeLast();
126
127             if (fullHistory.peekLast() == last) {
128                 fullHistory.removeLast();
129             }
130         }
131
132         var outcome2 = makeOperationOutcome2(outcome);
133         partialHistory.add(outcome2);
134         fullHistory.add(outcome2);
135     }
136
137     /**
138      * Makes a notification message for the current operation.
139      *
140      * @return a new notification
141      */
142     public VirtualControlLoopNotification makeNotification() {
143         var notif = new VirtualControlLoopNotification();
144         populateNotification(notif);
145
146         if (getFinalResult() != null) {
147             return notif;
148         }
149
150         OperationOutcome2 last = partialHistory.peekLast();
151         if (last == null) {
152             return notif;
153         }
154
155         notif.setMessage(last.getClOperation().toHistory());
156         notif.setHistory(partialHistory.stream().map(OperationOutcome2::getClOperation).collect(Collectors.toList()));
157
158         return notif;
159     }
160
161     /**
162      * Populates a notification structure.
163      *
164      * @param notif the notification to populate
165      */
166     protected void populateNotification(VirtualControlLoopNotification notif) {
167         notif.setNotification(ControlLoopNotificationType.OPERATION);
168         notif.setFrom("policy");
169         notif.setPolicyVersion(getPolicyVersion());
170     }
171
172     /**
173      * Get the last operation, as a message.
174      *
175      * @return the last operation, as a message
176      */
177     public String getOperationMessage() {
178         OperationOutcome2 last = fullHistory.peekLast();
179         return (last == null ? null : last.getClOperation().toMessage());
180     }
181
182     /**
183      * Makes a control loop response.
184      *
185      * @param outcome operation outcome
186      * @return a new control loop response, or {@code null} if none is required
187      */
188     public ControlLoopResponse makeControlLoopResponse(OperationOutcome outcome) {
189         var clRsp = new ControlLoopResponse();
190         clRsp.setFrom(outcome.getActor());
191
192         return clRsp;
193     }
194
195     @Getter
196     @ToString
197     public class OperationOutcome2 {
198         private final int attempt;
199         private final OperationOutcome outcome;
200         private final ControlLoopOperation clOperation;
201
202         /**
203          * Constructs the object.
204          *
205          * @param outcome outcome of the operation
206          */
207         public OperationOutcome2(OperationOutcome outcome) {
208             this.outcome = outcome;
209             this.attempt = attempts;
210
211             clOperation = outcome.toControlLoopOperation();
212
213             // TODO encode()?
214             OperationalTarget target = getPolicy().getActorOperation().getTarget();
215             String targetStr = (target != null ? target.toString() : null);
216             clOperation.setTarget(targetStr);
217
218             if (outcome.getEnd() == null) {
219                 clOperation.setOutcome("Started");
220             } else if (clOperation.getOutcome() == null) {
221                 clOperation.setOutcome("");
222             }
223         }
224     }
225
226     protected OperationOutcome2 makeOperationOutcome2(OperationOutcome outcome) {
227         return new OperationOutcome2(outcome);
228     }
229 }