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.util.ArrayList;
24 import java.util.LinkedHashMap;
25 import java.util.List;
27 import java.util.UUID;
29 import lombok.NoArgsConstructor;
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.ControlLoopElementDefinition;
35 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
37 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
38 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
39 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
40 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
41 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
42 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
43 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
44 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantIntermediaryParameters;
45 import org.onap.policy.models.base.PfModelException;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 * This class is responsible for managing the state of all control loops in the participant.
54 public class ControlLoopHandler {
55 private static final Logger LOGGER = LoggerFactory.getLogger(ControlLoopHandler.class);
57 private ToscaConceptIdentifier participantType = null;
58 private ToscaConceptIdentifier participantId = null;
59 private MessageSender messageSender = null;
61 private final Map<ToscaConceptIdentifier, ControlLoop> controlLoopMap = new LinkedHashMap<>();
63 private final Map<UUID, ControlLoopElement> elementsOnThisParticipant = new LinkedHashMap<>();
66 private List<ControlLoopElementListener> listeners = new ArrayList<>();
69 * Constructor, set the participant ID and messageSender.
71 * @param parameters the parameters of the participant
72 * @param messageSender the messageSender for sending responses to messages
74 public ControlLoopHandler(ParticipantIntermediaryParameters parameters, MessageSender messageSender) {
75 this.participantType = parameters.getParticipantType();
76 this.participantId = parameters.getParticipantId();
77 this.messageSender = messageSender;
80 public void registerControlLoopElementListener(ControlLoopElementListener listener) {
81 listeners.add(listener);
85 * Handle a control loop element state change message.
87 * @param id controlloop element id
88 * @param orderedState the current state
89 * @param newState the ordered state
90 * @return controlLoopElement the updated controlloop element
92 public ControlLoopElement updateControlLoopElementState(UUID id, ControlLoopOrderedState orderedState,
93 ControlLoopState newState) {
99 ControlLoopElement clElement = elementsOnThisParticipant.get(id);
100 if (clElement != null) {
101 clElement.setOrderedState(orderedState);
102 clElement.setState(newState);
103 LOGGER.debug("Control loop element {} state changed to {}", id, newState);
104 var response = new ParticipantResponseDetails();
105 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
106 response.setResponseMessage("ControlLoopElement state changed to {} " + newState);
107 messageSender.sendResponse(response);
115 * Handle a control loop element statistics.
117 * @param id controlloop element id
118 * @param elementStatistics control loop element Statistics
120 public void updateControlLoopElementStatistics(UUID id, ClElementStatistics elementStatistics) {
121 ControlLoopElement clElement = elementsOnThisParticipant.get(id);
122 if (clElement != null) {
123 elementStatistics.setParticipantId(participantId);
124 elementStatistics.setId(id);
125 clElement.setClElementStatistics(elementStatistics);
130 * Handle a control loop state change message.
132 * @param stateChangeMsg the state change message
134 public void handleControlLoopStateChange(ControlLoopStateChange stateChangeMsg) {
135 if (stateChangeMsg.getControlLoopId() == null) {
139 var controlLoop = controlLoopMap.get(stateChangeMsg.getControlLoopId());
141 if (controlLoop == null) {
142 LOGGER.debug("Control loop {} does not use this participant", stateChangeMsg.getControlLoopId());
146 var response = new ParticipantResponseDetails(stateChangeMsg);
147 handleState(controlLoop, response, stateChangeMsg.getOrderedState());
148 messageSender.sendResponse(response);
152 * Method to handle state changes.
154 * @param controlLoop participant response
155 * @param response participant response
156 * @param orderedState controlloop ordered state
158 private void handleState(final ControlLoop controlLoop, final ParticipantResponseDetails response,
159 ControlLoopOrderedState orderedState) {
160 switch (orderedState) {
162 handleUninitialisedState(controlLoop, orderedState, response);
165 handlePassiveState(controlLoop, orderedState, response);
168 handleRunningState(controlLoop, orderedState, response);
171 LOGGER.debug("StateChange message has no state, state is null {}", controlLoop.getDefinition());
177 * Handle a control loop update message.
179 * @param updateMsg the update message
181 public void handleControlLoopUpdate(ControlLoopUpdate updateMsg,
182 Map<UUID, ControlLoopElementDefinition> clElementDefinitions) {
184 if (!updateMsg.appliesTo(participantType, participantId)) {
188 var controlLoop = controlLoopMap.get(updateMsg.getControlLoopId());
190 var response = new ParticipantResponseDetails(updateMsg);
192 // TODO: Updates to existing ControlLoops are not supported yet (Addition/Removal of ControlLoop
193 // elements to existing ControlLoop has to be supported).
194 if (controlLoop != null) {
195 response.setResponseStatus(ParticipantResponseStatus.FAIL);
196 response.setResponseMessage("Control loop " + updateMsg.getControlLoopId()
197 + " already defined on participant " + participantId);
199 messageSender.sendResponse(response);
203 controlLoop = updateMsg.getControlLoop();
204 controlLoop.getElements().values().removeIf(element -> !participantType.equals(element.getParticipantType()));
206 controlLoopMap.put(updateMsg.getControlLoopId(), controlLoop);
207 for (ControlLoopElement element : updateMsg.getControlLoop().getElements().values()) {
208 element.setState(element.getOrderedState().asState());
209 element.setParticipantId(participantId);
210 elementsOnThisParticipant.put(element.getId(), element);
213 for (ControlLoopElementListener clElementListener : listeners) {
215 for (ControlLoopElement element : updateMsg.getControlLoop().getElements().values()) {
216 clElementListener.controlLoopElementUpdate(element,
217 clElementDefinitions.get(element.getId()).getControlLoopElementToscaServiceTemplate());
219 } catch (PfModelException e) {
220 LOGGER.debug("Control loop element update failed {}", updateMsg.getControlLoopId());
224 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
225 response.setResponseMessage(
226 "Control loop " + updateMsg.getControlLoopId() + " defined on participant " + participantId);
228 messageSender.sendResponse(response);
232 * Method to handle when the new state from participant is UNINITIALISED state.
234 * @param controlLoop participant response
235 * @param orderedState orderedState
236 * @param response participant response
238 private void handleUninitialisedState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
239 final ParticipantResponseDetails response) {
240 handleStateChange(controlLoop, orderedState, ControlLoopState.UNINITIALISED, response);
241 controlLoopMap.remove(controlLoop.getKey().asIdentifier());
243 for (ControlLoopElementListener clElementListener : listeners) {
245 for (ControlLoopElement element : controlLoop.getElements().values()) {
246 clElementListener.controlLoopElementStateChange(element.getId(), element.getState(), orderedState);
248 } catch (PfModelException e) {
249 LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
255 * Method to handle when the new state from participant is PASSIVE state.
257 * @param controlLoop participant response
258 * @param orderedState orderedState
259 * @param response participant response
261 private void handlePassiveState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
262 final ParticipantResponseDetails response) {
263 handleStateChange(controlLoop, orderedState, ControlLoopState.PASSIVE, response);
267 * Method to handle when the new state from participant is RUNNING state.
269 * @param controlLoop participant response
270 * @param orderedState orderedState
271 * @param response participant response
273 private void handleRunningState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
274 final ParticipantResponseDetails response) {
275 handleStateChange(controlLoop, orderedState, ControlLoopState.RUNNING, response);
279 * Method to update the state of control loop elements.
281 * @param controlLoop participant status in memory
282 * @param orderedState orderedState the new ordered state the participant should have
283 * @param newState new state of the control loop elements
284 * @param response the response to the state change request
286 private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
287 ControlLoopState newState, ParticipantResponseDetails response) {
289 if (orderedState.equals(controlLoop.getOrderedState())) {
290 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
291 response.setResponseMessage("Control loop is already in state " + orderedState);
295 if (!CollectionUtils.isEmpty(controlLoop.getElements().values())) {
296 controlLoop.getElements().values().forEach(element -> {
297 element.setState(newState);
298 element.setOrderedState(orderedState);
302 response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
303 response.setResponseMessage(
304 "ControlLoop state changed from " + controlLoop.getOrderedState() + " to " + orderedState);
305 controlLoop.setOrderedState(orderedState);
309 * Get control loops as a {@link ConrolLoops} class.
311 * @return the control loops
313 public ControlLoops getControlLoops() {
314 var controlLoops = new ControlLoops();
315 controlLoops.setControlLoopList(new ArrayList<>(controlLoopMap.values()));