2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.controlloop.participant.intermediary.handler;
23 import java.io.Closeable;
24 import java.util.ArrayList;
25 import java.util.LinkedHashMap;
26 import java.util.List;
28 import java.util.UUID;
30 import org.apache.commons.collections4.CollectionUtils;
31 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
32 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
33 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
34 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
35 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
37 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopStateChange;
38 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopUpdate;
39 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
40 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
41 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
42 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
43 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantIntermediaryParameters;
44 import org.onap.policy.models.base.PfModelException;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * This class is responsible for managing the state of all control loops in the participant.
52 public class ControlLoopHandler implements Closeable {
53 private static final Logger LOGGER = LoggerFactory.getLogger(ControlLoopHandler.class);
55 private ToscaConceptIdentifier participantId = null;
56 private MessageSender sender = null;
58 private final Map<ToscaConceptIdentifier, ControlLoop> controlLoopMap = new LinkedHashMap<>();
59 private final Map<UUID, ControlLoopElement> elementsOnThisParticipant = new LinkedHashMap<>();
62 private List<ControlLoopElementListener> listeners = new ArrayList<>();
64 public ControlLoopHandler() {
68 * Constructor, set the participant ID and sender.
70 * @param parameters the parameters of the participant
71 * @param sender the sender for sending responses to messages
73 public ControlLoopHandler(ParticipantIntermediaryParameters parameters, MessageSender sender) {
74 this.participantId = parameters.getParticipantId();
80 // No explicit action on this class
83 public void registerControlLoopElementListener(ControlLoopElementListener listener) {
84 listeners.add(listener);
88 * Handle a control loop element state change message.
90 * @param id controlloop element id
91 * @param state the updated state
92 * @return controlLoopElement the updated controlloop element
94 public ControlLoopElement updateControlLoopElementState(UUID id, ControlLoopOrderedState state) {
100 ControlLoopElement clElement = elementsOnThisParticipant.get(id);
101 if (clElement != null) {
102 clElement.setOrderedState(state);
103 LOGGER.debug("Control loop element {} ordered state changed to {}", id, state);
104 ParticipantResponseDetails response = new ParticipantResponseDetails();
105 sender.sendResponse(response);
106 return elementsOnThisParticipant.get(id);
112 public void updateControlLoopElementStatistics(ClElementStatistics elementStatistics) {
113 // TODO Handle statistics coming from a participant implementation
117 * Handle a control loop state change message.
119 * @param definition controlloop id
120 * @param state the updated state
121 * @return controlLoop the updated controlloop
123 public ControlLoop updateControlLoopState(ToscaConceptIdentifier definition, ControlLoopOrderedState state) {
124 if (definition == null) {
128 ControlLoop controlLoop = controlLoopMap.get(definition);
129 if (controlLoop == null) {
130 LOGGER.debug("Control loop {} does not use this participant", definition.getName());
134 ParticipantResponseDetails response = new ParticipantResponseDetails();
135 handleState(controlLoop, response, state);
136 sender.sendResponse(response);
141 * Handle a control loop state change message.
143 * @param stateChangeMsg the state change message
145 public void handleControlLoopStateChange(ParticipantControlLoopStateChange stateChangeMsg) {
146 if (stateChangeMsg.getControlLoopId() == null) {
150 ControlLoop controlLoop = controlLoopMap.get(stateChangeMsg.getControlLoopId());
152 if (controlLoop == null) {
153 LOGGER.debug("Control loop {} does not use this participant", stateChangeMsg.getControlLoopId());
157 ParticipantResponseDetails response = new ParticipantResponseDetails(stateChangeMsg);
158 handleState(controlLoop, response, stateChangeMsg.getOrderedState());
159 sender.sendResponse(response);
163 * Method to handle state changes.
165 * @param controlLoop participant response
166 * @param response participant response
167 * @param state controlloop ordered state
169 private void handleState(final ControlLoop controlLoop, final ParticipantResponseDetails response,
170 ControlLoopOrderedState state) {
173 handleUninitialisedState(controlLoop, response);
176 handlePassiveState(controlLoop, response);
179 handleRunningState(controlLoop, response);
182 LOGGER.debug("StateChange message has no state, state is null {}", controlLoop.getDefinition());
188 * Handle a control loop update message.
190 * @param updateMsg the update message
192 public void handleControlLoopUpdate(ParticipantControlLoopUpdate updateMsg) {
193 if (!updateMsg.appliesTo(participantId)) {
197 ControlLoop controlLoop = controlLoopMap.get(updateMsg.getControlLoopId());
199 ParticipantResponseDetails response = new ParticipantResponseDetails(updateMsg);
201 // TODO: Updates to existing ControlLoops are not supported yet (Addition/Removal of ControlLoop
202 // elements to existing ControlLoop has to be supported).
203 if (controlLoop != null) {
204 response.setResponseStatus(ParticipantResponseStatus.FAIL);
205 response.setResponseMessage("Control loop " + updateMsg.getControlLoopId()
206 + " already defined on participant " + participantId);
208 sender.sendResponse(response);
212 controlLoop = updateMsg.getControlLoop();
213 controlLoop.getElements().removeIf(element -> participantId.equals(element.getParticipantId()));
215 controlLoopMap.put(updateMsg.getControlLoopId(), controlLoop);
216 for (ControlLoopElement element : updateMsg.getControlLoop().getElements()) {
217 element.setState(element.getOrderedState().asState());
218 elementsOnThisParticipant.put(element.getId(), element);
221 for (ControlLoopElementListener clElementListener : listeners) {
223 clElementListener.controlLoopElementUpdate(null, updateMsg.getControlLoopDefinition());
224 } catch (PfModelException e) {
225 LOGGER.debug("Control loop element update failed {}", updateMsg.getControlLoopId());
229 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
230 response.setResponseMessage(
231 "Control loop " + updateMsg.getControlLoopId() + " defined on participant " + participantId);
233 sender.sendResponse(response);
237 * Method to handle when the new state from participant is UNINITIALISED state.
239 * @param controlLoop participant response
240 * @param response participant response
242 private void handleUninitialisedState(final ControlLoop controlLoop, final ParticipantResponseDetails response) {
243 handleStateChange(controlLoop, ControlLoopState.UNINITIALISED, response);
244 controlLoopMap.remove(controlLoop.getKey().asIdentifier());
248 * Method to handle when the new state from participant is PASSIVE state.
250 * @param controlLoop participant response
251 * @param response participant response
253 private void handlePassiveState(final ControlLoop controlLoop, final ParticipantResponseDetails response) {
254 handleStateChange(controlLoop, ControlLoopState.PASSIVE, response);
258 * Method to handle when the new state from participant is RUNNING state.
260 * @param controlLoop participant response
261 * @param response participant response
263 private void handleRunningState(final ControlLoop controlLoop, final ParticipantResponseDetails response) {
264 handleStateChange(controlLoop, ControlLoopState.RUNNING, response);
268 * Method to update the state of control loop elements.
270 * @param controlLoop participant status in memory
271 * @param state new state of the control loop elements
273 private void handleStateChange(ControlLoop controlLoop, ControlLoopState newState,
274 ParticipantResponseDetails response) {
276 if (newState.equals(controlLoop.getState())) {
277 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
278 response.setResponseMessage("Control loop is already in state " + newState);
282 if (!CollectionUtils.isEmpty(controlLoop.getElements())) {
283 controlLoop.getElements().forEach(element -> element.setState(newState));
286 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
287 response.setResponseMessage("ControlLoop state changed from " + controlLoop.getState() + " to " + newState);
288 controlLoop.setState(newState);
292 * Get control loops as a {@link ConrolLoops} class.
294 * @return the control loops
296 public ControlLoops getControlLoops() {
297 ControlLoops controlLoops = new ControlLoops();
298 controlLoops.setControlLoopList(new ArrayList<>(controlLoopMap.values()));